diff options
Diffstat (limited to 'indra/llcommon')
63 files changed, 883 insertions, 874 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 95e991c246..c4041f0c79 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -10,7 +10,6 @@ include(Boost)  include(LLSharedLibs)  include(Copy3rdPartyLibs)  include(ZLIBNG) -include(URIPARSER)  include(Tracy) @@ -19,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 @@ -128,8 +125,6 @@ set(llcommon_HEADER_FILES      lazyeventapi.h      linden_common.h      llalignedarray.h -    llallocator.h -    llallocator_heap_profile.h      llapp.h      llapr.h      llassettype.h @@ -268,6 +263,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}) @@ -278,7 +277,6 @@ target_link_libraries(          ll::expat          ll::zlib-ng          ll::boost -        ll::uriparser          ll::oslibraries          ll::tracy      ) 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 b85bd2573b..6da764f94c 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -90,7 +90,7 @@ bool LLApp::sDisableCrashlogger = false;  // Local flag for whether or not to do logging in signal handlers.  //static -bool LLApp::sLogInSignal = false; +bool LLApp::sLogInSignal = true;  // static  // Keeps track of application status @@ -373,6 +373,9 @@ static std::map<LLApp::EAppStatus, const char*> statusDesc  // static  void LLApp::setStatus(EAppStatus status)  { +    auto status_it = statusDesc.find(status); +    std::string status_text = status_it != statusDesc.end() ? std::string(status_it->second) : std::to_string(status); +    LL_INFOS() << "status: " << status_text << LL_ENDL;      // notify everyone waiting on sStatus any time its value changes      sStatus.set_all(status); @@ -381,18 +384,7 @@ void LLApp::setStatus(EAppStatus status)      if (! LLEventPumps::wasDeleted())      {          // notify interested parties of status change -        LLSD statsd; -        auto found = statusDesc.find(status); -        if (found != statusDesc.end()) -        { -            statsd = found->second; -        } -        else -        { -            // unknown status? at least report value -            statsd = LLSD::Integer(status); -        } -        LLEventPumps::instance().obtain("LLApp").post(llsd::map("status", statsd)); +        LLEventPumps::instance().obtain("LLApp").post(llsd::map("status", status_text));      }  } @@ -487,6 +479,33 @@ int LLApp::getPid()  #endif  } +// static +void LLApp::notifyOutOfDiskSpace() +{ +    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; + +    min_time_to_send = now + min_interval; + +    if (LLApp* app = instance()) +    { +        app->sendOutOfDiskSpaceNotification(); +    } +    else +    { +        LL_WARNS() << "No app instance" << LL_ENDL; +    } +} + +// virtual +void LLApp::sendOutOfDiskSpaceNotification() +{ +    LL_WARNS() << "Should never be called" << LL_ENDL; // Should be overridden +} +  #ifndef LL_WINDOWS  void setup_signals()  { @@ -654,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 @@ -691,11 +711,11 @@ 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;          }      }  } diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index ad8912ca88..d90ecdf661 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -202,6 +202,8 @@ public:      static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)      static int getPid(); +    static void notifyOutOfDiskSpace(); +      //      // Sleep for specified time while still running      // @@ -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]; diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index b085f8f5dc..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" @@ -606,7 +607,11 @@ S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset,          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/llcoros.h b/indra/llcommon/llcoros.h index 369d65407e..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" @@ -307,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/lldate.cpp b/indra/llcommon/lldate.cpp index c63c7012d1..b38864688d 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -41,20 +41,11 @@  #include "llstring.h"  #include "llfasttimer.h" -static const F64 DATE_EPOCH = 0.0; -  static const F64 LL_APR_USEC_PER_SEC = 1000000.0;      // should be APR_USEC_PER_SEC, but that relies on INT64_C which      // isn't defined in glib under our build set up for some reason -LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH) -{} - -LLDate::LLDate(const LLDate& date) : -    mSecondsSinceEpoch(date.mSecondsSinceEpoch) -{} -  LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :      mSecondsSinceEpoch(seconds_since_epoch.value())  {} diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 81f2dd0d1c..1a69a04232 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -43,16 +43,13 @@   */  class LL_COMMON_API LLDate  { +    static constexpr F64 DATE_EPOCH = 0.0;  public:      /**       * @brief Construct a date equal to epoch.       */ -    LLDate(); - -    /** -     * @brief Construct a date equal to the source date. -     */ -    LLDate(const LLDate& date); +    constexpr LLDate() : mSecondsSinceEpoch(DATE_EPOCH) +    {}      /**       * @brief Construct a date from a seconds since epoch value. diff --git a/indra/llcommon/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 fa24987d1c..41c69ba194 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -55,7 +55,7 @@  #include "llsingleton.h"  #include "llstl.h"  #include "lltimer.h" -#include <boost/fiber/recursive_mutex.hpp> +#include "llprofiler.h"  // On Mac, got:  // #error "Boost.Stacktrace requires `_Unwind_Backtrace` function. Define @@ -168,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; @@ -235,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: @@ -275,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 @@ -312,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);          } @@ -339,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);          }      }; @@ -507,7 +507,7 @@ namespace          LLError::TimeFunction               mTimeFunction;          Recorders                           mRecorders; -        boost::fibers::recursive_mutex      mRecorderMutex; +        LL_PROFILE_MUTEX_NAMED(LLCoros::RMutex, mRecorderMutex, "Log Recorders");          int                                 mShouldLogCallCounter; @@ -530,7 +530,6 @@ namespace          mCrashFunction(NULL),          mTimeFunction(NULL),          mRecorders(), -        mRecorderMutex(),          mShouldLogCallCounter(0)      {      } @@ -1045,7 +1044,7 @@ namespace LLError              return;          }          SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); -        std::unique_lock lock(s->mRecorderMutex); +        std::unique_lock lock(s->mRecorderMutex); LL_PROFILE_MUTEX_LOCK(s->mRecorderMutex);          s->mRecorders.push_back(recorder);      } @@ -1056,7 +1055,7 @@ namespace LLError              return;          }          SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); -        std::unique_lock 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());      } @@ -1105,7 +1104,7 @@ namespace LLError      std::shared_ptr<RECORDER> findRecorder()      {          SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); -        std::unique_lock lock(s->mRecorderMutex); +        std::unique_lock lock(s->mRecorderMutex); LL_PROFILE_MUTEX_LOCK(s->mRecorderMutex);          return findRecorderPos<RECORDER>(s).first;      } @@ -1116,7 +1115,7 @@ namespace LLError      bool removeRecorder()      {          SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); -        std::unique_lock lock(s->mRecorderMutex); +        std::unique_lock lock(s->mRecorderMutex); LL_PROFILE_MUTEX_LOCK(s->mRecorderMutex);          auto found = findRecorderPos<RECORDER>(s);          if (found.first)          { @@ -1216,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; -        std::unique_lock lock(s->mRecorderMutex); +        std::unique_lock lock(s->mRecorderMutex); LL_PROFILE_MUTEX_LOCK(s->mRecorderMutex);          for (LLError::RecorderPtr& r : s->mRecorders)          {              if (!r->enabled()) @@ -1281,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, @@ -1347,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;          } @@ -1392,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;          } @@ -1524,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;          } @@ -1549,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;          } @@ -1566,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;          } diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index cbb703e9e7..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: 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.h b/indra/llcommon/llevents.h index f97fca0a32..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> diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index ddf239f306..ed94ef21ef 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -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 */ @@ -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 2564671b13..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); @@ -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 ac52f90c9f..b4bcc80ac4 100644 --- a/indra/llcommon/llfindlocale.cpp +++ b/indra/llcommon/llfindlocale.cpp @@ -185,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/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/llmemory.cpp b/indra/llcommon/llmemory.cpp index 4b7d60d654..99c803e46f 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -39,6 +39,7 @@  #elif LL_LINUX  # include <unistd.h>  # include <sys/resource.h> +# include <sys/sysinfo.h>  #endif  #include "llmemory.h" @@ -50,13 +51,28 @@  //----------------------------------------------------------------------------  //static + +// most important memory metric for texture streaming +//  On Windows, this should agree with resource monitor -> performance -> memory -> available +//  On OS X, this should be activity monitor -> memory -> (physical memory - memory used) +// NOTE: this number MAY be less than the actual available memory on systems with more than MaxHeapSize64 GB of physical memory (default 16GB) +//  In that case, should report min(available, sMaxHeapSizeInKB-sAllocateMemInKB)  U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX); + +// Installed physical memory  U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0); -static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application"); -static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application"); + +// Maximimum heap size according to the user's settings (default 16GB) +U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); + +// Current memory usage  U32Kilobytes LLMemory::sAllocatedMemInKB(0); +  U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0); -U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); + + +static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application"); +static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application");  void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)  { @@ -84,7 +100,14 @@ void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size)  //static  void LLMemory::updateMemoryInfo()  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED; + +    sMaxPhysicalMemInKB = gSysMemory.getPhysicalMemoryKB(); + +    U32Kilobytes avail_mem; +    LLMemoryInfo::getAvailableMemoryKB(avail_mem); +    sAvailPhysicalMemInKB = avail_mem; +  #if LL_WINDOWS      PROCESS_MEMORY_COUNTERS counters; @@ -95,23 +118,9 @@ void LLMemory::updateMemoryInfo()      }      sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize)); -    sample(sAllocatedMem, sAllocatedMemInKB);      sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));      sample(sVirtualMem, sAllocatedPageSizeInKB); -    U32Kilobytes avail_phys, avail_virtual; -    LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ; -    sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB); - -    if(sMaxPhysicalMemInKB > sAllocatedMemInKB) -    { -        sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ; -    } -    else -    { -        sAvailPhysicalMemInKB = U32Kilobytes(0); -    } -  #elif defined(LL_DARWIN)      task_vm_info info;      mach_msg_type_number_t  infoCount = TASK_VM_INFO_COUNT; @@ -136,31 +145,19 @@ void LLMemory::updateMemoryInfo()      {          LL_WARNS() << "task_info failed" << LL_ENDL;      } - -    // Total installed and available physical memory are properties of the host, not just our process. -    vm_statistics64_data_t vmstat; -    mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; -    mach_port_t host = mach_host_self(); -    vm_size_t page_size; -    host_page_size(host, &page_size); -    kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count); -    if (result == KERN_SUCCESS) { -        // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.' -        // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure. -        sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size); -        sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize(); -      } -    else -    { -        LL_WARNS() << "task_info failed" << LL_ENDL; -    } - +#elif defined(LL_LINUX) +    // Use sysinfo() to get the total physical memory. +    struct sysinfo info; +    sysinfo(&info); +    sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(LLMemory::getCurrentRSS())); // represents the RAM allocated by this process only (in line with the windows implementation)  #else      //not valid for other systems for now. +    LL_WARNS() << "LLMemory::updateMemoryInfo() not implemented for this platform." << LL_ENDL;      sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS()); -    sMaxPhysicalMemInKB = U64Bytes(U32_MAX); -    sAvailPhysicalMemInKB = U64Bytes(U32_MAX);  #endif +    sample(sAllocatedMem, sAllocatedMemInKB); + +    sAvailPhysicalMemInKB = llmin(sAvailPhysicalMemInKB, sMaxHeapSizeInKB - sAllocatedMemInKB);      return ;  } @@ -192,16 +189,16 @@ void* LLMemory::tryToAlloc(void* address, U32 size)  //static  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 diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp index 40c651d9c1..be1ae89a25 100644 --- a/indra/llcommon/llmutex.cpp +++ b/indra/llcommon/llmutex.cpp @@ -100,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; @@ -124,7 +124,7 @@ LLThread::id_t LLMutex::lockingThread() const  bool LLMutex::trylock()  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      if (isSelfLocked())      { //redundant lock          mCount++; @@ -161,7 +161,7 @@ LLSharedMutex::LLSharedMutex()  bool LLSharedMutex::isLocked() const  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      std::lock_guard<std::mutex> lock(mLockMutex);      return !mLockingThreads.empty(); @@ -169,7 +169,7 @@ bool LLSharedMutex::isLocked() const  bool LLSharedMutex::isThreadLocked() const  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      LLThread::id_t current_thread = LLThread::currentID();      std::lock_guard<std::mutex> lock(mLockMutex); @@ -179,7 +179,7 @@ bool LLSharedMutex::isThreadLocked() const  void LLSharedMutex::lockShared()  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      LLThread::id_t current_thread = LLThread::currentID();      mLockMutex.lock(); @@ -204,7 +204,7 @@ void LLSharedMutex::lockShared()  void LLSharedMutex::lockExclusive()  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      LLThread::id_t current_thread = LLThread::currentID();      mLockMutex.lock(); @@ -237,7 +237,7 @@ void LLSharedMutex::lockExclusive()  bool LLSharedMutex::trylockShared()  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      LLThread::id_t current_thread = LLThread::currentID();      std::lock_guard<std::mutex> lock(mLockMutex); @@ -260,7 +260,7 @@ bool LLSharedMutex::trylockShared()  bool LLSharedMutex::trylockExclusive()  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      LLThread::id_t current_thread = LLThread::currentID();      std::lock_guard<std::mutex> lock(mLockMutex); @@ -282,7 +282,7 @@ bool LLSharedMutex::trylockExclusive()  void LLSharedMutex::unlockShared()  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      LLThread::id_t current_thread = LLThread::currentID();      std::lock_guard<std::mutex> lock(mLockMutex); @@ -303,7 +303,7 @@ void LLSharedMutex::unlockShared()  void LLSharedMutex::unlockExclusive()  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;      LLThread::id_t current_thread = LLThread::currentID();      std::lock_guard<std::mutex> lock(mLockMutex); @@ -338,20 +338,20 @@ 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();  } @@ -364,7 +364,7 @@ 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();  } @@ -373,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; @@ -388,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();  } @@ -400,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(); @@ -419,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/llpointer.h b/indra/llcommon/llpointer.h index f5916f9d58..6edff9fa5e 100644 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -46,8 +46,11 @@  template <class Type> class LLPointer  {  public: +    template<typename Subclass> +    friend class LLPointer; +      LLPointer() : -        mPointer(NULL) +        mPointer(nullptr)      {      } @@ -63,6 +66,12 @@ public:          ref();      } +    LLPointer(LLPointer<Type>&& ptr) noexcept +    { +        mPointer = ptr.mPointer; +        ptr.mPointer = nullptr; +    } +      // Support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.      template<typename Subclass>      LLPointer(const LLPointer<Subclass>& ptr) : @@ -71,6 +80,13 @@ public:          ref();      } +    template<typename Subclass> +    LLPointer(LLPointer<Subclass>&& ptr) noexcept : +        mPointer(ptr.get()) +    { +        ptr.mPointer = nullptr; +    } +      ~LLPointer()      {          unref(); @@ -82,11 +98,11 @@ public:      const Type& operator*() const               { return *mPointer; }      Type&   operator*()                         { return *mPointer; } -    operator BOOL() const                       { return (mPointer != NULL); } -    operator bool() const                       { return (mPointer != NULL); } -    bool operator!() const                      { return (mPointer == NULL); } -    bool isNull() const                         { return (mPointer == NULL); } -    bool notNull() const                        { return (mPointer != NULL); } +    operator BOOL() const                       { return (mPointer != nullptr); } +    operator bool() const                       { return (mPointer != nullptr); } +    bool operator!() const                      { return (mPointer == nullptr); } +    bool isNull() const                         { return (mPointer == nullptr); } +    bool notNull() const                        { return (mPointer != nullptr); }      operator Type*() const                      { return mPointer; }      bool operator !=(Type* ptr) const           { return (mPointer != ptr); } @@ -107,6 +123,17 @@ public:          return *this;      } +    LLPointer<Type>& operator =(LLPointer<Type>&& ptr) +    { +        if (mPointer != ptr.mPointer) +        { +            unref(); +            mPointer = ptr.mPointer; +            ptr.mPointer = nullptr; +        } +        return *this; +    } +      // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.      template<typename Subclass>      LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) @@ -115,6 +142,18 @@ public:          return *this;      } +    template<typename Subclass> +    LLPointer<Type>& operator =(LLPointer<Subclass>&& ptr) +    { +        if (mPointer != ptr.mPointer) +        { +            unref(); +            mPointer = ptr.mPointer; +            ptr.mPointer = nullptr; +        } +        return *this; +    } +      // Just exchange the pointers, which will not change the reference counts.      static void swap(LLPointer<Type>& a, LLPointer<Type>& b)      { @@ -141,9 +180,9 @@ protected:          if (mPointer)          {              Type *temp = mPointer; -            mPointer = NULL; +            mPointer = nullptr;              temp->unref(); -            if (mPointer != NULL) +            if (mPointer != nullptr)              {                  LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;                  unref(); @@ -168,9 +207,11 @@ protected:  template <class Type> class LLConstPointer  { +    template<typename Subclass> +    friend class LLConstPointer;  public:      LLConstPointer() : -        mPointer(NULL) +        mPointer(nullptr)      {      } @@ -186,6 +227,12 @@ public:          ref();      } +    LLConstPointer(LLConstPointer<Type>&& ptr) noexcept +    { +        mPointer = ptr.mPointer; +        ptr.mPointer = nullptr; +    } +      // support conversion up the type hierarchy.  See Item 45 in Effective C++, 3rd Ed.      template<typename Subclass>      LLConstPointer(const LLConstPointer<Subclass>& ptr) : @@ -194,6 +241,13 @@ public:          ref();      } +    template<typename Subclass> +    LLConstPointer(LLConstPointer<Subclass>&& ptr) noexcept : +        mPointer(ptr.get()) +    { +        ptr.mPointer = nullptr; +    } +      ~LLConstPointer()      {          unref(); @@ -203,11 +257,11 @@ public:      const Type* operator->() const              { return mPointer; }      const Type& operator*() const               { return *mPointer; } -    operator BOOL() const                       { return (mPointer != NULL); } -    operator bool() const                       { return (mPointer != NULL); } -    bool operator!() const                      { return (mPointer == NULL); } -    bool isNull() const                         { return (mPointer == NULL); } -    bool notNull() const                        { return (mPointer != NULL); } +    operator BOOL() const                       { return (mPointer != nullptr); } +    operator bool() const                       { return (mPointer != nullptr); } +    bool operator!() const                      { return (mPointer == nullptr); } +    bool isNull() const                         { return (mPointer == nullptr); } +    bool notNull() const                        { return (mPointer != nullptr); }      operator const Type*() const                { return mPointer; }      bool operator !=(const Type* ptr) const     { return (mPointer != ptr); } @@ -239,6 +293,17 @@ public:          return *this;      } +    LLConstPointer<Type>& operator =(LLConstPointer<Type>&& ptr) +    { +        if (mPointer != ptr.mPointer) +        { +            unref(); +            mPointer = ptr.mPointer; +            ptr.mPointer = nullptr; +        } +        return *this; +    } +      // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.      template<typename Subclass>      LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr) @@ -252,6 +317,18 @@ public:          return *this;      } +    template<typename Subclass> +    LLConstPointer<Type>& operator =(LLConstPointer<Subclass>&& ptr) +    { +        if (mPointer != ptr.mPointer) +        { +            unref(); +            mPointer = ptr.mPointer; +            ptr.mPointer = nullptr; +        } +        return *this; +    } +      // Just exchange the pointers, which will not change the reference counts.      static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)      { @@ -278,9 +355,9 @@ protected:          if (mPointer)          {              const Type *temp = mPointer; -            mPointer = NULL; +            mPointer = nullptr;              temp->unref(); -            if (mPointer != NULL) +            if (mPointer != nullptr)              {                  LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;                  unref(); @@ -313,7 +390,7 @@ public:      :   LLPointer<Type>(ptr),          mStayUnique(false)      { -        if (ptr.mForceUnique) +        if (ptr.mStayUnique)          {              makeUnique();          } diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 0248e8f8b9..a528cc7fd8 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -74,9 +74,6 @@      #ifndef LL_MSVC          #define LL_MSVC 1      #endif -    #if _MSC_VER < 1400 -        #define LL_MSVC7 //Visual C++ 2003 or earlier -    #endif  #endif  // Deal with minor differences on Unixy OSes. @@ -130,8 +127,6 @@  #endif  // level 4 warnings that we need to disable: -#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 : 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  #endif  //  LL_MSVC diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index 166da8f424..39ed29c1b4 100644 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -32,7 +32,6 @@  #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> 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 722d9afca2..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 diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 7d77f6f6a9..1c4ac5a7bf 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -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); 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/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 e95d2e6c1c..5d38e55686 100644 --- a/indra/llcommon/llsdjson.cpp +++ b/indra/llcommon/llsdjson.cpp @@ -35,16 +35,7 @@  #include "llerror.h"  #include "../llmath/llmath.h" -#if LL_WINDOWS -#pragma warning (push) -#pragma warning (disable : 4702) // compiler thinks unreachable code -#endif  #include <boost/json/src.hpp> -#if LL_WINDOWS -#pragma warning (pop) -#endif - -  //=========================================================================  LLSD LlsdFromJson(const boost::json::value& val) 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 15002580c9..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 @@ -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> 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 dd3a58c26d..12f67208c1 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -51,7 +51,7 @@  // U32  LLSD ll_sd_from_U32(const U32 val)  { -    std::vector<U8> v; +    LLSD::Binary v;      U32 net_order = htonl(val);      v.resize(4); @@ -63,7 +63,7 @@ LLSD ll_sd_from_U32(const U32 val)  U32 ll_U32_from_sd(const LLSD& sd)  {      U32 ret; -    std::vector<U8> v = sd.asBinary(); +    const LLSD::Binary& v = sd.asBinary();      if (v.size() < 4)      {          return 0; @@ -76,7 +76,7 @@ U32 ll_U32_from_sd(const LLSD& sd)  //U64  LLSD ll_sd_from_U64(const U64 val)  { -    std::vector<U8> v; +    LLSD::Binary v;      U32 high, low;      high = (U32)(val >> 32); @@ -94,7 +94,7 @@ LLSD ll_sd_from_U64(const U64 val)  U64 ll_U64_from_sd(const LLSD& sd)  {      U32 high, low; -    std::vector<U8> v = sd.asBinary(); +    const LLSD::Binary& v = sd.asBinary();      if (v.size() < 8)      { @@ -112,7 +112,7 @@ U64 ll_U64_from_sd(const LLSD& sd)  // IP Address (stored in net order in a U32, so don't need swizzling)  LLSD ll_sd_from_ipaddr(const U32 val)  { -    std::vector<U8> v; +    LLSD::Binary v;      v.resize(4);      memcpy(&(v[0]), &val, 4);       /* Flawfinder: ignore */ @@ -123,7 +123,7 @@ LLSD ll_sd_from_ipaddr(const U32 val)  U32 ll_ipaddr_from_sd(const LLSD& sd)  {      U32 ret; -    std::vector<U8> v = sd.asBinary(); +    const LLSD::Binary& v = sd.asBinary();      if (v.size() < 4)      {          return 0; @@ -135,17 +135,17 @@ U32 ll_ipaddr_from_sd(const LLSD& sd)  // Converts an LLSD binary to an LLSD string  LLSD ll_string_from_binary(const LLSD& sd)  { -    std::vector<U8> value = sd.asBinary(); +    const LLSD::Binary& value = sd.asBinary();      std::string str;      str.resize(value.size()); -    memcpy(&str[0], &value[0], value.size()); +    memcpy(&str[0], value.data(), value.size());      return str;  }  // Converts an LLSD string to an LLSD binary  LLSD ll_binary_from_string(const LLSD& sd)  { -    std::vector<U8> binary_value; +    LLSD::Binary binary_value;      std::string string_value = sd.asString();      for (const U8 c : string_value) @@ -214,7 +214,7 @@ bool compare_llsd_with_template(      const LLSD& template_llsd,      LLSD& resultant_llsd)  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      if (          llsd_to_test.isUndefined() && @@ -337,7 +337,7 @@ bool filter_llsd_with_template(      const LLSD & template_llsd,      LLSD & resultant_llsd)  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      if (llsd_to_test.isUndefined() && template_llsd.isDefined())      { @@ -533,7 +533,7 @@ class TypeLookup  public:      TypeLookup()      { -        LL_PROFILE_ZONE_SCOPED +        LL_PROFILE_ZONE_SCOPED;          for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di)          { @@ -543,7 +543,7 @@ public:      std::string lookup(LLSD::Type type) const      { -        LL_PROFILE_ZONE_SCOPED +        LL_PROFILE_ZONE_SCOPED;          MapType::const_iterator found = mMap.find(type);          if (found != mMap.end()) @@ -595,7 +595,7 @@ static std::string match_types(LLSD::Type expect, // prototype.type()                                 LLSD::Type actual,        // type we're checking                                 const std::string& pfx)   // as for llsd_matches  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      // Trivial case: if the actual type is exactly what we expect, we're good.      if (actual == expect) @@ -634,7 +634,7 @@ static std::string match_types(LLSD::Type expect, // prototype.type()  // see docstring in .h file  std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx)  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      // An undefined prototype means that any data is valid.      // An undefined slot in an array or map prototype means that any data @@ -768,7 +768,7 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str  bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      // We're comparing strict equality of LLSD representation rather than      // performing any conversions. So if the types aren't equal, the LLSD @@ -878,7 +878,7 @@ namespace llsd  LLSD& drill_ref(LLSD& blob, const LLSD& rawPath)  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      // Treat rawPath uniformly as an array. If it's not already an array,      // store it as the only entry in one. (But let's say Undefined means an @@ -905,7 +905,7 @@ LLSD& drill_ref(LLSD& blob, const LLSD& rawPath)      // path entry that's bad.      for (LLSD::Integer i = 0; i < path.size(); ++i)      { -        LL_PROFILE_ZONE_NUM( i ) +        LL_PROFILE_ZONE_NUM(i);          const LLSD& key{path[i]};          if (key.isString()) @@ -935,7 +935,7 @@ LLSD& drill_ref(LLSD& blob, const LLSD& rawPath)  LLSD drill(const LLSD& blob, const LLSD& path)  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      // drill_ref() does exactly what we want. Temporarily cast away      // const-ness and use that. @@ -949,7 +949,7 @@ LLSD drill(const LLSD& blob, const LLSD& path)  // filter may be include to exclude/include keys in a map.  LLSD llsd_clone(LLSD value, LLSD filter)  { -    LL_PROFILE_ZONE_SCOPED +    LL_PROFILE_ZONE_SCOPED;      LLSD clone;      bool has_filter(filter.isMap()); @@ -990,8 +990,7 @@ LLSD llsd_clone(LLSD value, LLSD filter)      case LLSD::TypeBinary:      { -        LLSD::Binary bin(value.asBinary().begin(), value.asBinary().end()); -        clone = LLSD::Binary(bin); +        clone = LLSD::Binary(value.asBinary().begin(), value.asBinary().end());          break;      }      default: diff --git a/indra/llcommon/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 7c6be25309..b5659e053c 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -35,9 +35,12 @@  #include "lockstatic.h"  #include "llthread.h"               // on_main_thread()  #include "llmainthreadtask.h" +#include "llprofiler.h" +#include "llerror.h"  #ifdef LL_WINDOWS -#pragma warning( disable : 4506 )   // no definition for inline function +#pragma warning(push) +#pragma warning(disable : 4506)   // no definition for inline function  #endif  class LLSingletonBase: private boost::noncopyable @@ -297,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}; @@ -419,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; @@ -447,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)          { @@ -504,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)              { @@ -594,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;      } @@ -604,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;      }  }; @@ -643,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)          { @@ -707,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)          { @@ -861,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 bda3579f60..ca8f4299d9 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -33,10 +33,7 @@  #include <sstream>  #include "llwin32headerslean.h" -#pragma warning (push) -#pragma warning (disable:4091) // a microsoft header has warnings. Very nice.  #include <dbghelp.h> -#pragma warning (pop)  typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(      IN ULONG frames_to_skip, diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 1b52d94258..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())      { diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 514d73b24b..505789f9ea 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -250,7 +250,7 @@ LLWString utf16str_to_wstring(const U16* utf16str, size_t len)      while (i < len)      {          llwchar cur_char; -        i += utf16chars_to_wchar(chars16+i, &cur_char); +        i += (S32)utf16chars_to_wchar(chars16+i, &cur_char);          wout += cur_char;      }      return wout; @@ -900,6 +900,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)  { @@ -1208,6 +1213,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. diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 123f4184b5..db716b1431 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -46,7 +46,6 @@  #endif  #include <string.h> -#include <boost/scoped_ptr.hpp>  const char LL_UNKNOWN_CHAR = '?';  class LLSD; @@ -832,8 +831,10 @@ 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()); }  //@} @@ -890,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       * diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index cfb05873df..79625ad9f8 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -74,6 +74,8 @@ using namespace llsd;  #   include <mach/mach_host.h>  #   include <mach/task.h>  #   include <mach/task_info.h> +#   include <sys/types.h> +#   include <mach/mach_init.h>  #elif LL_LINUX  #   include <errno.h>  #   include <sys/utsname.h> @@ -85,6 +87,7 @@ const char MEMINFO_FILE[] = "/proc/meminfo";  #endif  LLCPUInfo gSysCPU; +LLMemoryInfo gSysMemory;  // Don't log memory info any more often than this. It also serves as our  // framerate sample size. @@ -797,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: @@ -874,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  } @@ -928,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"; @@ -977,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); diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index f97d49eeb1..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. @@ -169,6 +169,7 @@ bool LL_COMMON_API gunzip_file(const std::string& srcfile, const std::string& ds  // 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/llthread.cpp b/indra/llcommon/llthread.cpp index faaaefd561..e5d25b52f0 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -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,13 +411,13 @@ 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();  } diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index a3e871661c..28d6e4e4cc 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -91,7 +91,7 @@ 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 @@ -101,7 +101,7 @@ U32 micro_sleep(U64 us, U32 max_yields)      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);  } 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 ba7acf9547..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; diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 1ec83be7cb..c23adca7e8 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -229,7 +229,7 @@ F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& s      update();      const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];      const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL; -    return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value(); +    return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / (F32)mElapsedSeconds.value();  }  bool Recording::hasValue(const StatType<CountAccumulator>& stat) @@ -296,11 +296,11 @@ F64 Recording::getMean( const StatType<SampleAccumulator>& stat )      const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;      if (active_accumulator && active_accumulator->hasValue())      { -        F32 t = 0.0f; +        F64 t = 0.0;          S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();          if (div > 0)          { -            t = active_accumulator->getSampleCount() / div; +            t = (F64)active_accumulator->getSampleCount() / (F64)div;          }          return lerp(accumulator.getMean(), active_accumulator->getMean(), t);      } @@ -319,7 +319,7 @@ F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )      if (active_accumulator && active_accumulator->hasValue())      {          F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator); -        return sqrtf(sum_of_squares / (accumulator.getSamplingTime() + active_accumulator->getSamplingTime())); +        return sqrt(sum_of_squares / (F64)(accumulator.getSamplingTime() + active_accumulator->getSamplingTime()));      }      else      { @@ -382,11 +382,11 @@ F64 Recording::getMean( const StatType<EventAccumulator>& stat )      const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;      if (active_accumulator && active_accumulator->hasValue())      { -        F32 t = 0.0f; +        F64 t = 0.0;          S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();          if (div > 0)          { -            t = active_accumulator->getSampleCount() / div; +            t = (F64)active_accumulator->getSampleCount() / (F64)div;          }          return lerp(accumulator.getMean(), active_accumulator->getMean(), t);      } @@ -405,7 +405,7 @@ F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )      if (active_accumulator && active_accumulator->hasValue())      {          F64 sum_of_squares = EventAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator); -        return sqrtf(sum_of_squares / (accumulator.getSampleCount() + active_accumulator->getSampleCount())); +        return sqrt(sum_of_squares / (F64)(accumulator.getSampleCount() + active_accumulator->getSampleCount()));      }      else      { diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 985f06cd59..ad4c91d85b 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -35,6 +35,11 @@  #include "llpointer.h"  #include <limits> +#ifdef LL_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4244) // possible loss of data on conversions +#endif +  class LLStopWatchControlsMixinCommon  {  public: @@ -714,4 +719,8 @@ namespace LLTrace      };  } +#ifdef LL_WINDOWS +#pragma warning(pop) +#endif +  #endif // LL_LLTRACERECORDING_H diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h index 83ce0d05a8..bb1408609a 100644 --- a/indra/llcommon/llunittype.h +++ b/indra/llcommon/llunittype.h @@ -31,6 +31,11 @@  #include "llpreprocessor.h"  #include "llerror.h" +#ifdef LL_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4244) // possible loss of data on conversions +#endif +  //lightweight replacement of type traits for simple type equality check  template<typename S, typename T>  struct LLIsSameType @@ -846,4 +851,8 @@ LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, un      typedef LLUnit<U64, ns::unit_name> U64##unit_name;                  \      typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit +#ifdef LL_WINDOWS +#pragma warning(pop) +#endif +  #endif //LL_UNITTYPE_H diff --git a/indra/llcommon/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 3b37365ec7..7aeabc3c4a 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -31,6 +31,7 @@  // 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" diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp index 0057a1f639..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 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/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/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index fb2af1d2db..fae9f7023f 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -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/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  | 
