diff options
author | nat-goodspeed <nat@lindenlab.com> | 2024-09-05 15:40:12 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-05 15:40:12 -0400 |
commit | 04568da18d2261f3f7b851cf5341b766c9648204 (patch) | |
tree | 83d5db1c173636bb77ebb33e860fac77ab5d79e8 /indra/llcommon | |
parent | 18d81e20f0b0044c16615953d7b69d7fb34d3449 (diff) | |
parent | ff2d79906ccef217194d5d9ec9d7025db03592a8 (diff) |
Merge pull request #2513 from secondlife/lua-merge-dev
Merge develop branch into Lua project branch.
Diffstat (limited to 'indra/llcommon')
72 files changed, 1195 insertions, 1521 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3b157fd28f..f47136f781 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) @@ -21,8 +20,6 @@ set(llcommon_SOURCE_FILES hbxxh.cpp indra_constants.cpp lazyeventapi.cpp - llallocator.cpp - llallocator_heap_profile.cpp llapp.cpp llapr.cpp llassettype.cpp @@ -31,7 +28,6 @@ set(llcommon_SOURCE_FILES llbase64.cpp llbitpack.cpp llcallbacklist.cpp - llcallstack.cpp llcleanup.cpp llcommon.cpp llcommonutils.cpp @@ -137,8 +133,6 @@ set(llcommon_HEADER_FILES lazyeventapi.h linden_common.h llalignedarray.h - llallocator.h - llallocator_heap_profile.h llapp.h llapr.h llassettype.h @@ -148,7 +142,6 @@ set(llcommon_HEADER_FILES llbitpack.h llboost.h llcallbacklist.h - llcallstack.h llcleanup.h llcommon.h llcommonutils.h @@ -283,6 +276,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}) @@ -293,7 +290,6 @@ target_link_libraries( ll::expat ll::zlib-ng ll::boost - ll::uriparser ll::oslibraries ll::tracy ) diff --git a/indra/llcommon/coro_scheduler.cpp b/indra/llcommon/coro_scheduler.cpp index 393356a39b..02b9f11333 100644 --- a/indra/llcommon/coro_scheduler.cpp +++ b/indra/llcommon/coro_scheduler.cpp @@ -26,7 +26,7 @@ namespace llcoro { -const F32 scheduler::DEFAULT_TIMESLICE{ LL::Timers::DEFAULT_TIMESLICE }; +const F64 scheduler::DEFAULT_TIMESLICE{ LL::Timers::DEFAULT_TIMESLICE }; const std::string qname("General"); @@ -72,7 +72,7 @@ boost::fibers::context* scheduler::pick_next() noexcept // When the main fiber is ready, and it's been more than mTimeslice since // the main fiber last ran, it's time to intervene. - F32 elapsed(now - mMainLast); + F64 elapsed(now - mMainLast); if (mMainCtx && elapsed > mTimeslice) { // We claim that the main fiber is not only stored in mMainCtx, but is diff --git a/indra/llcommon/coro_scheduler.h b/indra/llcommon/coro_scheduler.h index cc7e75d798..eee2d746b5 100644 --- a/indra/llcommon/coro_scheduler.h +++ b/indra/llcommon/coro_scheduler.h @@ -38,7 +38,7 @@ class scheduler: public boost::fibers::algo::round_robin public: // If the main fiber is ready, and it's been at least this long since the // main fiber last ran, jump the main fiber to the head of the queue. - static const F32 DEFAULT_TIMESLICE; + static const F64 DEFAULT_TIMESLICE; scheduler(); void awakened( boost::fibers::context*) noexcept override; @@ -57,11 +57,11 @@ private: bool mMainRunning{ false }; // If it's been at least this long since the last time the main fiber got // control, jump it to the head of the queue. - F32 mTimeslice{ DEFAULT_TIMESLICE }; + F64 mTimeslice{ DEFAULT_TIMESLICE }; // Timestamp as of the last time we suspended the main fiber. - F32 mMainLast{ 0 }; + F64 mMainLast{ 0 }; // Timestamp of start time - F32 mStart{ 0 }; + F64 mStart{ 0 }; // count context switches U64 mSwitches{ 0 }; // WorkQueue for deferred logging 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 101ca78e3b..820ba05f30 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/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp index 7cbe7a8c02..7b05c25c21 100644 --- a/indra/llcommon/llcallbacklist.cpp +++ b/indra/llcommon/llcallbacklist.cpp @@ -205,7 +205,7 @@ F32 Timers::timeUntilCall(handle_t timer) const } else { - return found->second.mTime - now(); + return narrow(found->second.mTime - now()); } } @@ -436,7 +436,7 @@ void TimersListener::scheduleAfter(const LLSD& params) // ditch mHandles entry mHandles.erase(key); }, - after)); + narrow(after))); } void TimersListener::scheduleEvery(const LLSD& params) @@ -461,7 +461,7 @@ void TimersListener::scheduleEvery(const LLSD& params) // we can't use a handshake -- always keep the ball rolling return false; }, - every)); + narrow(every))); } LLSD TimersListener::cancel(const LLSD& params) diff --git a/indra/llcommon/llcallstack.cpp b/indra/llcommon/llcallstack.cpp deleted file mode 100644 index c0be4f598e..0000000000 --- a/indra/llcommon/llcallstack.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @file llcallstack.cpp - * @brief run-time extraction of the current callstack - * - * $LicenseInfo:firstyear=2016&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2016, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llcommon.h" -#include "llcallstack.h" -#include "StackWalker.h" -#include "llthreadlocalstorage.h" - -#if LL_WINDOWS -class LLCallStackImpl: public StackWalker -{ -public: - LLCallStackImpl(): - StackWalker(false,0) // non-verbose, options = 0 - { - } - ~LLCallStackImpl() - { - } - void getStack(std::vector<std::string>& stack, S32 skip_count=0, bool verbose=false) - { - m_stack.clear(); - ShowCallstack(verbose); - // Skip the first few lines because they're just bookkeeping for LLCallStack, - // plus any additional lines requested to skip. - S32 first_line = skip_count + 3; - for (S32 i=first_line; i<m_stack.size(); ++i) - { - stack.push_back(m_stack[i]); - } - } -protected: - virtual void OnOutput(LPCSTR szText) - { - m_stack.push_back(szText); - } - std::vector<std::string> m_stack; -}; -#else -// Stub - not implemented currently on other platforms. -class LLCallStackImpl -{ -public: - LLCallStackImpl() {} - ~LLCallStackImpl() {} - void getStack(std::vector<std::string>& stack, S32 skip_count=0, bool verbose=false) - { - stack.clear(); - } -}; -#endif - -LLCallStackImpl *LLCallStack::s_impl = NULL; - -LLCallStack::LLCallStack(S32 skip_count, bool verbose): - m_skipCount(skip_count), - m_verbose(verbose) -{ - if (!s_impl) - { - s_impl = new LLCallStackImpl; - } - LLTimer t; - s_impl->getStack(m_strings, m_skipCount, m_verbose); -} - -bool LLCallStack::contains(const std::string& str) -{ - for (const std::string& src_str : m_strings) - { - if (src_str.find(str) != std::string::npos) - { - return true; - } - } - return false; -} - -std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack) -{ -#ifndef LL_RELEASE_FOR_DOWNLOAD - for (const std::string& str : call_stack.m_strings) - { - s << str; - } -#else - s << "UNAVAILABLE IN RELEASE"; -#endif - return s; -} - -LLContextStrings::LLContextStrings() -{ -} - -// static -LLContextStrings* LLContextStrings::getThreadLocalInstance() -{ - LLContextStrings *cons = LLThreadLocalSingletonPointer<LLContextStrings>::getInstance(); - if (!cons) - { - LLThreadLocalSingletonPointer<LLContextStrings>::setInstance(new LLContextStrings); - } - return LLThreadLocalSingletonPointer<LLContextStrings>::getInstance(); -} - -// static -void LLContextStrings::addContextString(const std::string& str) -{ - LLContextStrings *cons = getThreadLocalInstance(); - //LL_INFOS() << "CTX " << (S32)cons << " ADD " << str << " CNT " << cons->m_contextStrings[str] << LL_ENDL; - cons->m_contextStrings[str]++; -} - -// static -void LLContextStrings::removeContextString(const std::string& str) -{ - LLContextStrings *cons = getThreadLocalInstance(); - cons->m_contextStrings[str]--; - //LL_INFOS() << "CTX " << (S32)cons << " REMOVE " << str << " CNT " << cons->m_contextStrings[str] << LL_ENDL; - if (cons->m_contextStrings[str] == 0) - { - cons->m_contextStrings.erase(str); - } -} - -// static -bool LLContextStrings::contains(const std::string& str) -{ - const std::map<std::string,S32>& strings = - LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->m_contextStrings; - for (const std::map<std::string,S32>::value_type& str_pair : strings) - { - if (str_pair.first.find(str) != std::string::npos) - { - return true; - } - } - return false; -} - -// static -void LLContextStrings::output(std::ostream& os) -{ - const std::map<std::string,S32>& strings = - LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->m_contextStrings; - for (const std::map<std::string,S32>::value_type& str_pair : strings) - { - os << str_pair.first << "[" << str_pair.second << "]" << "\n"; - } -} - -// static -std::ostream& operator<<(std::ostream& s, const LLContextStatus& context_status) -{ - LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->output(s); - return s; -} - -bool LLContextStatus::contains(const std::string& str) -{ - return LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->contains(str); -} diff --git a/indra/llcommon/llcallstack.h b/indra/llcommon/llcallstack.h deleted file mode 100644 index ad10a9dbf7..0000000000 --- a/indra/llcommon/llcallstack.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file llcallstack.h - * @brief run-time extraction of the current callstack - * - * $LicenseInfo:firstyear=2016&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2016, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include <map> - -class LLCallStackImpl; - -class LLCallStack -{ -public: - LLCallStack(S32 skip_count=0, bool verbose=false); - std::vector<std::string> m_strings; - bool m_verbose; - bool contains(const std::string& str); -private: - static LLCallStackImpl *s_impl; - S32 m_skipCount; -}; - -LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack); - -class LLContextStrings -{ -public: - LLContextStrings(); - static void addContextString(const std::string& str); - static void removeContextString(const std::string& str); - static void output(std::ostream& os); - static LLContextStrings* getThreadLocalInstance(); - static bool contains(const std::string& str); -private: - std::map<std::string,S32> m_contextStrings; -}; - -class LLScopedContextString -{ -public: - LLScopedContextString(const std::string& str): - m_str(str) - { - LLContextStrings::addContextString(m_str); - } - ~LLScopedContextString() - { - LLContextStrings::removeContextString(m_str); - } -private: - std::string m_str; -}; - -// Mostly exists as a class to hook an ostream override to. -struct LLContextStatus -{ - bool contains(const std::string& str); -}; - -LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLContextStatus& context_status); - -#define dumpStack(tag) \ - LL_DEBUGS(tag) << "STACK:\n" \ - << "====================\n" \ - << LLCallStack() \ - << "====================" \ - << LL_ENDL; diff --git a/indra/llcommon/llcoromutex.h b/indra/llcommon/llcoromutex.h index 3405e79478..c0ceac4b22 100644 --- a/indra/llcommon/llcoromutex.h +++ b/indra/llcommon/llcoromutex.h @@ -18,11 +18,13 @@ // e.g. #include LLCOROS_MUTEX_HEADER #define LLCOROS_MUTEX_HEADER <boost/fiber/mutex.hpp> +#define LLCOROS_RMUTEX_HEADER <boost/fiber/recursive_mutex.hpp> #define LLCOROS_CONDVAR_HEADER <boost/fiber/condition_variable.hpp> namespace boost { namespace fibers { class mutex; + class recursive_mutex; enum class cv_status; class condition_variable; } @@ -47,6 +49,12 @@ static Future<T> getFuture(Promise<T>& promise) { return promise.get_future(); } // 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/llcoros.h b/indra/llcommon/llcoros.h index b7ca1af109..0291d7f1d9 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -320,6 +320,8 @@ public: // use mutex, lock, condition_variable suitable for coroutines using Mutex = llcoro::Mutex; + using RMutex = llcoro::RMutex; + // LockType is deprecated; see llcoromutex.h using LockType = llcoro::LockType; using cv_status = llcoro::cv_status; using ConditionVariable = llcoro::ConditionVariable; diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 592b7cff1b..5f51f40232 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -48,13 +48,6 @@ static const LLDate::timestamp LL_APR_USEC_PER_SEC = 1000000.0; // 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 772f45ea7c..0afe0b0599 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -43,18 +43,15 @@ */ class LL_COMMON_API LLDate { + static constexpr F64 DATE_EPOCH = 0.0; public: using timestamp = F64; /** * @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 51267c8e79..e6fe1eca75 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 @@ -64,6 +64,8 @@ #define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED #include <boost/stacktrace.hpp> +#include LLCOROS_RMUTEX_HEADER + namespace { #if LL_WINDOWS void debugger_print(const std::string& s) @@ -168,7 +170,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 +237,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 +277,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 +314,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 +341,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 +509,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 +532,6 @@ namespace mCrashFunction(NULL), mTimeFunction(NULL), mRecorders(), - mRecorderMutex(), mShouldLogCallCounter(0) { } @@ -1045,7 +1046,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 +1057,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 +1106,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 +1117,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 +1217,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 +1282,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 +1345,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 +1390,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; } @@ -1525,8 +1523,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; } @@ -1550,8 +1548,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; } @@ -1567,8 +1565,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; } @@ -1646,19 +1644,3 @@ namespace LLError sLocalizedOutOfMemoryWarning = message; } } - -void crashdriver(void (*callback)(int*)) -{ - // The LLERROR_CRASH macro used to have inline code of the form: - //int* make_me_crash = NULL; - //*make_me_crash = 0; - - // But compilers are getting smart enough to recognize that, so we must - // assign to an address supplied by a separate source file. We could do - // the assignment here in crashdriver() -- but then BugSplat would group - // all LL_ERRS() crashes as the fault of this one function, instead of - // identifying the specific LL_ERRS() source line. So instead, do the - // assignment in a lambda in the caller's source. We just provide the - // nullptr target. - callback(nullptr); -} diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 6176ce0d1d..8a143ff30a 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -408,9 +408,11 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; #define LL_NEWLINE '\n' // Use this only in LL_ERRS or in a place that LL_ERRS may not be used -#define LLERROR_CRASH \ -{ \ - crashdriver([](int* ptr){ *ptr = 0; exit(*ptr); }); \ +#define LLERROR_CRASH \ +{ \ + int* make_me_crash = (int*)0xDEADBEEFDEADBEEFUL; \ + *make_me_crash = 0; \ + exit(*make_me_crash); \ } #define LL_ENDL \ @@ -512,7 +514,4 @@ LL_DEBUGS("SomeTag") performs the locking and map-searching ONCE, then caches the result in a static variable. */ -// used by LLERROR_CRASH -void crashdriver(void (*)(int*)); - #endif // LL_LLERROR_H diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 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 de706d72eb..09ef81a6f5 100644 --- a/indra/llcommon/lleventfilter.h +++ b/indra/llcommon/lleventfilter.h @@ -367,7 +367,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 f92257238d..d339a09117 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -39,16 +39,8 @@ #include <string> #include <type_traits> #include <vector> -#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/optional/optional.hpp> #include "llcoromutex.h" #include "lldependencies.h" 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 f45144085b..03418e9bad 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&); @@ -103,7 +103,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 @@ -222,7 +223,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; @@ -238,19 +239,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 @@ -392,7 +393,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 @@ -511,14 +513,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/llmd5.cpp b/indra/llcommon/llmd5.cpp index f64f54c262..e999b8f597 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -68,10 +68,6 @@ documentation and/or software. */ - - - - #include "linden_common.h" #include "llmd5.h" @@ -81,232 +77,203 @@ documentation and/or software. // how many bytes to grab at a time when checking files const int LLMD5::BLOCK_LEN = 4096; - // LLMD5 simple initialization method - LLMD5::LLMD5() { - init(); + init(); } - - - // MD5 block update operation. Continues an MD5 message-digest // operation, processing another message block, and updating the // context. +void LLMD5::update(const uint8_t* input, const size_t input_length) +{ + size_t input_index, buffer_index; + size_t buffer_space; // how much space is left in buffer -void LLMD5::update (const uint8_t *input, const size_t input_length) { - - size_t input_index, buffer_index; - size_t buffer_space; // how much space is left in buffer - - if (finalized){ // so we can't update! - std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl; - return; - } - - // Compute number of bytes mod 64 - buffer_index = size_t((count >> 3) & 0x3F); + if (finalized) + { // so we can't update! + std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl; + return; + } - // Update number of bits - count += input_length << 3; + // Compute number of bytes mod 64 + buffer_index = size_t((count >> 3) & 0x3F); - buffer_space = 64 - buffer_index; // how much space is left in buffer + // Update number of bits + count += input_length << 3; - // now, transform each 64-byte piece of the input, bypassing the buffer - if (input == NULL || input_length == 0){ - std::cerr << "LLMD5::update: Invalid input!" << std::endl; - return; - } + buffer_space = 64 - buffer_index; // how much space is left in buffer - // Transform as many times as possible. - if (input_length >= buffer_space) { // ie. we have enough to fill the buffer - // fill the rest of the buffer and transform - memcpy( /* Flawfinder: ignore */ - buffer + buffer_index, - input, - buffer_space); - transform (buffer); + // now, transform each 64-byte piece of the input, bypassing the buffer + if (input == NULL || input_length == 0) + { + std::cerr << "LLMD5::update: Invalid input!" << std::endl; + return; + } - for (input_index = buffer_space; input_index + 63 < input_length; - input_index += 64) - transform (input+input_index); + // Transform as many times as possible. + if (input_length >= buffer_space) // ie. we have enough to fill the buffer + { + // fill the rest of the buffer and transform + memcpy(/* Flawfinder: ignore */ + buffer + buffer_index, + input, + buffer_space); + transform(buffer); - buffer_index = 0; // so we can buffer remaining - } - else - input_index=0; // so we can buffer the whole input + for (input_index = buffer_space; input_index + 63 < input_length; input_index += 64) + transform(input + input_index); + buffer_index = 0; // so we can buffer remaining + } + else + input_index = 0; // so we can buffer the whole input - // and here we do the buffering: - memcpy(buffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */ + // and here we do the buffering: + memcpy(buffer + buffer_index, input + input_index, input_length - input_index); /* Flawfinder: ignore */ } - - // MD5 update for files. // Like above, except that it works on files (and uses above as a primitive.) +void LLMD5::update(FILE* file) +{ + unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ + int len; -void LLMD5::update(FILE* file){ - - unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ - int len; - - while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) ) - update(buffer, len); - - fclose (file); + while ((len = (int)fread(buffer, 1, BLOCK_LEN, file))) + update(buffer, len); + fclose(file); } // MD5 update for istreams. // Like update for files; see above. +void LLMD5::update(std::istream& stream) +{ + unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ + int len; -void LLMD5::update(std::istream& stream){ - - unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ - int len; - - while (stream.good()){ - stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable. - len=(int)stream.gcount(); - update(buffer, len); - } - + while (stream.good()) + { + stream.read((char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable. + len = (int)stream.gcount(); + update(buffer, len); + } } -void LLMD5::update(const std::string& s) +void LLMD5::update(const std::string& s) { - update((unsigned char *)s.c_str(),s.length()); + update((unsigned char*)s.c_str(), s.length()); } // MD5 finalization. Ends an MD5 message-digest operation, writing the // the message digest and zeroizing the context. - - -void LLMD5::finalize (){ - - unsigned char bits[8]; /* Flawfinder: ignore */ - size_t index, padLen; - static uint8_t PADDING[64]={ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +void LLMD5::finalize() +{ + unsigned char bits[8]; /* Flawfinder: ignore */ + size_t index, padLen; + static uint8_t PADDING[64] = + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - if (finalized){ - std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl; - return; - } - - // Save number of bits. - // Treat count, a uint64_t, as uint32_t[2]. - encode (bits, reinterpret_cast<uint32_t*>(&count), 8); + if (finalized) + { + std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl; + return; + } - // Pad out to 56 mod 64. - index = size_t((count >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - update (PADDING, padLen); + // Save number of bits. + // Treat count, a uint64_t, as uint32_t[2]. + encode(bits, reinterpret_cast<uint32_t*>(&count), 8); - // Append length (before padding) - update (bits, 8); + // Pad out to 56 mod 64. + index = size_t((count >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update(PADDING, padLen); - // Store state in digest - encode (digest, state, 16); + // Append length (before padding) + update(bits, 8); - // Zeroize sensitive information - memset (buffer, 0, sizeof(*buffer)); + // Store state in digest + encode(digest, state, 16); - finalized=1; + // Zeroize sensitive information + memset(buffer, 0, sizeof(buffer)); + finalized = true; } - - - -LLMD5::LLMD5(FILE *file){ - - init(); // must be called be all constructors - update(file); - finalize (); +LLMD5::LLMD5(FILE* file) +{ + init(); // must be called be all constructors + update(file); + finalize(); } - - - -LLMD5::LLMD5(std::istream& stream){ - - init(); // must called by all constructors - update (stream); - finalize(); +LLMD5::LLMD5(std::istream& stream) +{ + init(); // must called by all constructors + update(stream); + finalize(); } // Digest a string of the format ("%s:%i" % (s, number)) -LLMD5::LLMD5(const unsigned char *string, const unsigned int number) +LLMD5::LLMD5(const unsigned char* string, const unsigned int number) { - const char *colon = ":"; - char tbuf[16]; /* Flawfinder: ignore */ + const char* colon = ":"; + char tbuf[16]; /* Flawfinder: ignore */ init(); - update(string, (U32)strlen((const char *) string)); /* Flawfinder: ignore */ - update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */ - snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */ - update((const unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */ + update(string, (U32)strlen((const char*)string)); /* Flawfinder: ignore */ + update((const unsigned char*)colon, (U32)strlen(colon)); /* Flawfinder: ignore */ + snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */ + update((const unsigned char*)tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */ finalize(); } // Digest a string -LLMD5::LLMD5(const unsigned char *s) +LLMD5::LLMD5(const unsigned char* s) { init(); - update(s, (U32)strlen((const char *) s)); /* Flawfinder: ignore */ + update(s, (U32)strlen((const char*)s)); /* Flawfinder: ignore */ finalize(); } -void LLMD5::raw_digest(unsigned char *s) const +void LLMD5::raw_digest(unsigned char* s) const { if (!finalized) { - std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "<< - "finalized the digest!" << std::endl; + std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't " + << "finalized the digest!" << std::endl; s[0] = '\0'; return; } - memcpy(s, digest, 16); /* Flawfinder: ignore */ - return; + memcpy(s, digest, 16); /* Flawfinder: ignore */ } - - -void LLMD5::hex_digest(char *s) const +void LLMD5::hex_digest(char* s) const { - int i; - if (!finalized) { - std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "<< - "finalized the digest!" <<std::endl; + std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't " + << "finalized the digest!" << std::endl; s[0] = '\0'; return; } - for (i=0; i<16; i++) + for (int i = 0; i < 16; i++) { - sprintf(s+i*2, "%02x", digest[i]); /* Flawfinder: ignore */ + sprintf(s + i * 2, "%02x", digest[i]); /* Flawfinder: ignore */ } - s[32]='\0'; - - return; + s[32] = '\0'; } - - - - - -std::ostream& operator<<(std::ostream &stream, LLMD5 context) +std::ostream& operator<<(std::ostream& stream, const LLMD5& context) { char s[33]; /* Flawfinder: ignore */ context.hex_digest(s); @@ -320,7 +287,7 @@ bool operator==(const LLMD5& a, const LLMD5& b) unsigned char b_guts[16]; a.raw_digest(a_guts); b.raw_digest(b_guts); - if (memcmp(a_guts,b_guts,16)==0) + if (memcmp(a_guts, b_guts, 16) == 0) return true; else return false; @@ -328,30 +295,27 @@ bool operator==(const LLMD5& a, const LLMD5& b) bool operator!=(const LLMD5& a, const LLMD5& b) { - return !(a==b); + return !(a == b); } // PRIVATE METHODS: +void LLMD5::init() +{ + finalized = false; // we just started! -void LLMD5::init(){ - finalized=0; // we just started! - - // Nothing counted, so count=0 - count = 0; + // Nothing counted, so count=0 + count = 0; - // Load magic initialization constants. - state[0] = 0x67452301; - state[1] = 0xefcdab89; - state[2] = 0x98badcfe; - state[3] = 0x10325476; + // Load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; } - - // Constants for MD5Transform routine. // Although we could use C++ style constants, defines are actually better, // since they let us easily evade scope clashes. - #define S11 7 #define S12 12 #define S13 17 @@ -381,153 +345,144 @@ void LLMD5::init(){ /* ROTATE_LEFT rotates x left n bits. */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - - +#define FF(a, b, c, d, x, s, ac) \ + { \ + (a) += F((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + { \ + (a) += G((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + { \ + (a) += H((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + { \ + (a) += I((b), (c), (d)) + (x) + (U32)(ac); \ + (a) = ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } // LLMD5 basic transformation. Transforms state based on block. -void LLMD5::transform (const U8 block[64]){ - - uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - decode (x, block, 64); - - assert(!finalized); // not just a user error, since the method is private - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - // Zeroize sensitive information. - memset ( (uint8_t *) x, 0, sizeof(x)); - +void LLMD5::transform(const U8 block[64]) +{ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + decode(x, block, 64); + + assert(!finalized); // not just a user error, since the method is private + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof(x)); } - - // Encodes input (uint32_t) into output (unsigned char). Assumes len is // a multiple of 4. -void LLMD5::encode (uint8_t *output, const uint32_t *input, const size_t len) { - - size_t i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (uint8_t) (input[i] & 0xff); - output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff); - output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff); - output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff); - } +void LLMD5::encode(uint8_t* output, const uint32_t* input, const size_t len) +{ + for (size_t i = 0, j = 0; j < len; i++, j += 4) + { + output[j] = (uint8_t)(input[i] & 0xff); + output[j + 1] = (uint8_t)((input[i] >> 8) & 0xff); + output[j + 2] = (uint8_t)((input[i] >> 16) & 0xff); + output[j + 3] = (uint8_t)((input[i] >> 24) & 0xff); + } } - - - // Decodes input (unsigned char) into output (uint32_t). Assumes len is // a multiple of 4. -void LLMD5::decode (uint32_t *output, const uint8_t *input, const size_t len){ - - size_t i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | - (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24); +void LLMD5::decode(uint32_t* output, const uint8_t* input, const size_t len) +{ + for (size_t i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | + (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24); } - - diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 46c79cf5a2..ad063fda46 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -67,59 +67,57 @@ documentation and/or software. */ -#include <cstdint> // uint32_t et al. +#include <cstdint> // uint32_t et al. // use for the raw digest output const int MD5RAW_BYTES = 16; // use for outputting hex digests -const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null +const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null const int MD5HEX_STR_BYTES = 32; // message system fixed size -class LL_COMMON_API LLMD5 { -// how many bytes to grab at a time when checking files - static const int BLOCK_LEN; +class LL_COMMON_API LLMD5 +{ + // how many bytes to grab at a time when checking files + static const int BLOCK_LEN; public: -// methods for controlled operation: - LLMD5 (); // simple initializer - void update (const uint8_t *input, const size_t input_length); - void update (std::istream& stream); - void update (FILE *file); - void update (const std::string& str); - void finalize (); - -// constructors for special circumstances. All these constructors finalize -// the MD5 context. - LLMD5 (const unsigned char *string); // digest string, finalize - LLMD5 (std::istream& stream); // digest stream, finalize - LLMD5 (FILE *file); // digest file, close, finalize - LLMD5 (const unsigned char *string, const unsigned int number); - -// methods to acquire finalized result - void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data - void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string - - friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 context); + // methods for controlled operation: + LLMD5(); // simple initializer + void update(const uint8_t* input, const size_t input_length); + void update(std::istream& stream); + void update(FILE* file); + void update(const std::string& str); + void finalize(); + + // constructors for special circumstances. All these constructors finalize + // the MD5 context. + LLMD5(const unsigned char* string); // digest string, finalize + LLMD5(std::istream& stream); // digest stream, finalize + LLMD5(FILE* file); // digest file, close, finalize + LLMD5(const unsigned char* string, const unsigned int number); + + // methods to acquire finalized result + void raw_digest(unsigned char* array) const; // provide 16-byte array for binary data + void hex_digest(char* string) const; // provide 33-byte array for ascii-hex string + + friend LL_COMMON_API std::ostream& operator<<(std::ostream&, const LLMD5& context); private: - - -// next, the private data: - uint32_t state[4]; - uint64_t count; // number of *bits*, mod 2^64 - uint8_t buffer[64]; // input buffer - uint8_t digest[16]; - uint8_t finalized; - -// last, the private methods, mostly static: - void init (); // called by all constructors - void transform (const uint8_t *buffer); // does the real update work. Note - // that length is implied to be 64. - - static void encode (uint8_t *dest, const uint32_t *src, const size_t length); - static void decode (uint32_t *dest, const uint8_t *src, const size_t length); - + // next, the private data: + uint32_t state[4]; + uint64_t count; // number of *bits*, mod 2^64 + uint8_t buffer[64]; // input buffer + uint8_t digest[16]; + bool finalized; + + // last, the private methods, mostly static: + void init(); // called by all constructors + void transform(const uint8_t* buffer); // does the real update work. Note + // that length is implied to be 64. + + static void encode(uint8_t* dest, const uint32_t* src, const size_t length); + static void decode(uint32_t* dest, const uint8_t* src, const size_t length); }; LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b); diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 4b7d60d654..ba48319a16 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -39,6 +39,7 @@ #elif LL_LINUX # include <unistd.h> # include <sys/resource.h> +# include <sys/sysinfo.h> #endif #include "llmemory.h" @@ -50,13 +51,28 @@ //---------------------------------------------------------------------------- //static + +// most important memory metric for texture streaming +// On Windows, this should agree with resource monitor -> performance -> memory -> available +// On OS X, this should be activity monitor -> memory -> (physical memory - memory used) +// NOTE: this number MAY be less than the actual available memory on systems with more than MaxHeapSize64 GB of physical memory (default 16GB) +// In that case, should report min(available, sMaxHeapSizeInKB-sAllocateMemInKB) U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX); + +// Installed physical memory U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0); -static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application"); -static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application"); + +// Maximimum heap size according to the user's settings (default 16GB) +U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); + +// Current memory usage U32Kilobytes LLMemory::sAllocatedMemInKB(0); + U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0); -U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); + + +static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application"); +static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application"); void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) { @@ -84,7 +100,14 @@ void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size) //static void LLMemory::updateMemoryInfo() { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; + + sMaxPhysicalMemInKB = gSysMemory.getPhysicalMemoryKB(); + + U32Kilobytes avail_mem; + LLMemoryInfo::getAvailableMemoryKB(avail_mem); + sAvailPhysicalMemInKB = avail_mem; + #if LL_WINDOWS PROCESS_MEMORY_COUNTERS counters; @@ -95,23 +118,9 @@ void LLMemory::updateMemoryInfo() } sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize)); - sample(sAllocatedMem, sAllocatedMemInKB); sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage)); sample(sVirtualMem, sAllocatedPageSizeInKB); - U32Kilobytes avail_phys, avail_virtual; - LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ; - sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB); - - if(sMaxPhysicalMemInKB > sAllocatedMemInKB) - { - sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ; - } - else - { - sAvailPhysicalMemInKB = U32Kilobytes(0); - } - #elif defined(LL_DARWIN) task_vm_info info; mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT; @@ -120,7 +129,7 @@ void LLMemory::updateMemoryInfo() { // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of // memory that the memory manager has committed for a running process", which is rss. - sAllocatedPageSizeInKB = U32Bytes(info.resident_size); + sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(info.resident_size)); // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less. @@ -130,37 +139,25 @@ void LLMemory::updateMemoryInfo() // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint. // // (On Windows, we use WorkingSetSize.) - sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable); + sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(info.resident_size - info.reusable)); } else { LL_WARNS() << "task_info failed" << LL_ENDL; } - - // Total installed and available physical memory are properties of the host, not just our process. - vm_statistics64_data_t vmstat; - mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; - mach_port_t host = mach_host_self(); - vm_size_t page_size; - host_page_size(host, &page_size); - kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count); - if (result == KERN_SUCCESS) { - // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.' - // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure. - sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size); - sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize(); - } - else - { - LL_WARNS() << "task_info failed" << LL_ENDL; - } - +#elif defined(LL_LINUX) + // Use sysinfo() to get the total physical memory. + struct sysinfo info; + sysinfo(&info); + sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(LLMemory::getCurrentRSS())); // represents the RAM allocated by this process only (in line with the windows implementation) #else //not valid for other systems for now. + LL_WARNS() << "LLMemory::updateMemoryInfo() not implemented for this platform." << LL_ENDL; sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS()); - sMaxPhysicalMemInKB = U64Bytes(U32_MAX); - sAvailPhysicalMemInKB = U64Bytes(U32_MAX); #endif + sample(sAllocatedMem, sAllocatedMemInKB); + + sAvailPhysicalMemInKB = llmin(sAvailPhysicalMemInKB, sMaxHeapSizeInKB - sAllocatedMemInKB); return ; } @@ -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 15e47d6c89..adf1f49001 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 02ff02cedc..2a38d6d896 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -60,9 +60,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 01e9ca9951..d3417a233e 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -36,10 +36,12 @@ #include "mutex.h" #include "lockstatic.h" #include "apply.h" +#include "llprofiler.h" #include "llthread.h" // on_main_thread() #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 @@ -312,7 +314,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}; @@ -434,7 +436,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; @@ -467,7 +469,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) { @@ -524,7 +526,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) { @@ -606,7 +608,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; } @@ -616,7 +618,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; } }; @@ -661,7 +663,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) { @@ -724,7 +726,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) { @@ -878,4 +880,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 e49e293756..e4be1efaed 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -48,7 +48,6 @@ #endif #include <string.h> -#include <boost/scoped_ptr.hpp> const char LL_UNKNOWN_CHAR = '?'; class LLSD; @@ -869,8 +868,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()); } //@} @@ -927,6 +928,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 cd3bbb21df..0e352bce0f 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 e1f41faa44..9ca1ca4e2e 100644 --- a/indra/llcommon/tests/lleventfilter_test.cpp +++ b/indra/llcommon/tests/lleventfilter_test.cpp @@ -82,13 +82,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 -----*/ @@ -101,12 +101,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*/ @@ -117,7 +117,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 fcec139d7a..ff0607f503 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -1807,7 +1807,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 |