diff options
Diffstat (limited to 'indra/llcommon')
24 files changed, 189 insertions, 530 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index df65828d02..3d073b009c 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -14,19 +14,6 @@ include(ZLIBNG) include(URIPARSER) include(Tracy) -include_directories( - ${EXPAT_INCLUDE_DIRS} - ${LLCOMMON_INCLUDE_DIRS} - ${JSONCPP_INCLUDE_DIR} - ${ZLIBNG_INCLUDE_DIRS} - ${URIPARSER_INCLUDE_DIRS} - ${TRACY_INCLUDE_DIR} - ) - -# add_executable(lltreeiterators lltreeiterators.cpp) -# -# target_link_libraries(lltreeiterators -# ${LLCOMMON_LIBRARIES}) set(llcommon_SOURCE_FILES indra_constants.cpp @@ -108,7 +95,6 @@ set(llcommon_SOURCE_FILES llsys.cpp lltempredirect.cpp llthread.cpp - llthreadlocalstorage.cpp llthreadsafequeue.cpp lltimer.cpp lltrace.cpp @@ -272,52 +258,25 @@ if (DARWIN) list(APPEND llcommon_SOURCE_FILES llsys_objc.mm) endif (DARWIN) -set_source_files_properties(${llcommon_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -if (USE_BUGSPLAT) - set_source_files_properties(${llcommon_SOURCE_FILES} - PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") -endif (USE_BUGSPLAT) - list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) -if(LLCOMMON_LINK_SHARED) - add_library (llcommon SHARED ${llcommon_SOURCE_FILES}) - if(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - ##add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) - endif(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - # always generate llcommon.pdb, even for "Release" builds - set_target_properties(llcommon PROPERTIES LINK_FLAGS "/DEBUG") - endif(WINDOWS) - ll_stage_sharedlib(llcommon) -else(LLCOMMON_LINK_SHARED) - add_library (llcommon ${llcommon_SOURCE_FILES}) -endif(LLCOMMON_LINK_SHARED) +add_library (llcommon ${llcommon_SOURCE_FILES}) target_link_libraries( - llcommon - ${APRUTIL_LIBRARIES} - ${APR_LIBRARIES} - ${EXPAT_LIBRARIES} - ${JSONCPP_LIBRARIES} - ${ZLIBNG_LIBRARIES} - ${WINDOWS_LIBRARIES} - ${BOOST_FIBER_LIBRARY} - ${BOOST_CONTEXT_LIBRARY} - ${BOOST_PROGRAM_OPTIONS_LIBRARY} - ${BOOST_REGEX_LIBRARY} - ${BOOST_SYSTEM_LIBRARY} - ${GOOGLE_PERFTOOLS_LIBRARIES} - ${URIPARSER_LIBRARIES} - ${TRACY_LIBRARY} + llcommon + ll::apr + ll::expat + ll::jsoncpp + ll::zlib-ng + ll::boost + ll::uriparser + ll::oslibraries + ll::tracy ) +target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(llcommon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + add_dependencies(llcommon stage_third_party_libs) if (LL_TESTS) @@ -328,14 +287,7 @@ if (LL_TESTS) LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") #set(TEST_DEBUG on) - set(test_libs llcommon - ${LLCOMMON_LIBRARIES} - ${WINDOWS_LIBRARIES} - ${GOOGLEMOCK_LIBRARIES} - ${BOOST_FIBER_LIBRARY} - ${BOOST_CONTEXT_LIBRARY} - ${BOOST_THREAD_LIBRARY} - ${BOOST_SYSTEM_LIBRARY}) + set(test_libs llcommon) LL_ADD_INTEGRATION_TEST(bitpack "" "${test_libs}") LL_ADD_INTEGRATION_TEST(classic_callback "" "${test_libs}") LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}") diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 8ddd132793..3ff8d16bbb 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -68,10 +68,6 @@ void setup_signals(); void default_unix_signal_handler(int signum, siginfo_t *info, void *); #if LL_LINUX -#include "google_breakpad/minidump_descriptor.h" -static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, - void* context, - bool succeeded); #else // Called by breakpad exception handler after the minidump has been generated. bool unix_post_minidump_callback(const char *dump_dir, @@ -856,47 +852,8 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } #if LL_LINUX -bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded) -{ - // Copy minidump file path into fixed buffer in the app instance to avoid - // heap allocations in a crash handler. - - // path format: <dump_dir>/<minidump_id>.dmp - - //HACK: *path points to the buffer in getMiniDumpFilename which has already allocated space - //to avoid doing allocation during crash. - char * path = LLApp::instance()->getMiniDumpFilename(); - int dir_path_len = strlen(path); - - // The path must not be truncated. - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len; - - llassert( (remaining - strlen(minidump_desc.path())) > 5); - - path += dir_path_len; - - if (dir_path_len > 0 && path[-1] != '/') - { - *path++ = '/'; - --remaining; - } - - strncpy(path, minidump_desc.path(), remaining); - - LL_INFOS("CRASHREPORT") << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL; - LLApp::runErrorHandler(); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - clear_signals(); - return false; -#else - return true; #endif -} -#endif - - bool unix_post_minidump_callback(const char *dump_dir, const char *minidump_id, void *context, bool succeeded) diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index db94765871..435531f86f 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -30,7 +30,6 @@ #include "llapr.h" #include "llmutex.h" #include "apr_dso.h" -#include "llthreadlocalstorage.h" apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool. @@ -54,7 +53,6 @@ void ll_init_apr() LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ; } - LLThreadLocalPointerBase::initAllThreadLocalStorage(); gAPRInitialized = true; } @@ -70,8 +68,6 @@ void ll_cleanup_apr() LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL; - LLThreadLocalPointerBase::destroyAllThreadLocalStorage(); - if (gAPRPoolp) { apr_pool_destroy(gAPRPoolp); diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 14bfb98629..70d8dfc8b9 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -288,25 +288,15 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl return name; } +namespace +{ + #if LL_WINDOWS static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) +U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) { - // C++ exceptions were logged in toplevelTryWrapper, but not SEH - // log SEH exceptions here, to make sure it gets into bugsplat's - // report and because __try won't allow std::string operations - if (code != STATUS_MSC_EXCEPTION) - { - LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL; - } - // Handle bugsplat here, since GetExceptionInformation() can only be - // called from within filter for __except(filter), not from __except's {} - // Bugsplat should get all exceptions, C++ and SEH - LLApp::instance()->reportCrashToBugsplat(exception_infop); - - // Only convert non C++ exceptions. if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on @@ -319,28 +309,38 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, } } -void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable) +void sehandle(const LLCoros::callable_t& callable) { __try { - LLCoros::toplevelTryWrapper(name, callable); + callable(); } - __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) { - // convert to C++ styled exception for handlers other than bugsplat + // convert to C++ styled exception // Note: it might be better to use _se_set_translator // if you want exception to inherit full callstack - // - // in case of bugsplat this will get to exceptionTerminateHandler and - // looks like fiber will terminate application after that char integer_string[512]; - sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); throw std::exception(integer_string); } } -#endif -void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) +#else // ! LL_WINDOWS + +inline void sehandle(const LLCoros::callable_t& callable) +{ + callable(); +} + +#endif // ! LL_WINDOWS + +} // anonymous namespace + +// Top-level wrapper around caller's coroutine callable. +// Normally we like to pass strings and such by const reference -- but in this +// case, we WANT to copy both the name and the callable to our local stack! +void LLCoros::toplevel(std::string name, callable_t callable) { // keep the CoroData on this top-level function's stack frame CoroData corodata(name); @@ -350,12 +350,12 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call // run the code the caller actually wants in the coroutine try { - callable(); + sehandle(callable); } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -366,36 +366,14 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call } catch (...) { -#if LL_WINDOWS - // Any OTHER kind of uncaught exception will cause the viewer to - // crash, SEH handling should catch it and report to bugsplat. - LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); - // to not modify callstack - throw; -#else // Stash any OTHER kind of uncaught exception in the rethrow() queue // to be rethrown by the main fiber. LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine " << name << LL_ENDL; LLCoros::instance().saveException(name, std::current_exception()); -#endif } } -// Top-level wrapper around caller's coroutine callable. -// Normally we like to pass strings and such by const reference -- but in this -// case, we WANT to copy both the name and the callable to our local stack! -void LLCoros::toplevel(std::string name, callable_t callable) -{ -#if LL_WINDOWS - // Because SEH can's have unwinding, need to call a wrapper - // 'try' is inside SEH handling to not catch LLContinue - sehHandle(name, callable); -#else - toplevelTryWrapper(name, callable); -#endif -} - //static void LLCoros::checkStop() { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index dbff921f16..966ce03296 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -307,11 +307,7 @@ public: private: std::string generateDistinctName(const std::string& prefix) const; - void toplevelTryWrapper(const std::string& name, const callable_t& callable); -#if LL_WINDOWS - void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper -#endif - void toplevel(std::string name, callable_t callable); // calls sehHandle or toplevelTryWrapper + void toplevel(std::string name, callable_t callable); struct CoroData; static CoroData& get_CoroData(const std::string& caller); void saveException(const std::string& name, std::exception_ptr exc); diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 919d2dabc4..56fb7c21ca 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -943,7 +943,7 @@ namespace LLError for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a) { const LLSD& entry = *a; - if (entry.isMap() && !entry.emptyMap()) + if (entry.isMap() && entry.size() != 0) { ELevel level = decodeLevel(entry["level"]); diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 23936f0526..97a38ea992 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -272,6 +272,14 @@ public: boost::bind(&ReadPipeImpl::tick, this, _1)); } + ~ReadPipeImpl() + { + if (mConnection.connected()) + { + mConnection.disconnect(); + } + } + // Much of the implementation is simply connecting the abstract virtual // methods with implementation data concealed from the base class. virtual std::istream& get_istream() { return mStream; } diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 24cb9bbce1..3daaef44fc 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -421,42 +421,42 @@ public: static std::string typeString(Type type); // Return human-readable type as a string }; -struct llsd_select_bool : public std::unary_function<LLSD, LLSD::Boolean> +struct llsd_select_bool { LLSD::Boolean operator()(const LLSD& sd) const { return sd.asBoolean(); } }; -struct llsd_select_integer : public std::unary_function<LLSD, LLSD::Integer> +struct llsd_select_integer { LLSD::Integer operator()(const LLSD& sd) const { return sd.asInteger(); } }; -struct llsd_select_real : public std::unary_function<LLSD, LLSD::Real> +struct llsd_select_real { LLSD::Real operator()(const LLSD& sd) const { return sd.asReal(); } }; -struct llsd_select_float : public std::unary_function<LLSD, F32> +struct llsd_select_float { F32 operator()(const LLSD& sd) const { return (F32)sd.asReal(); } }; -struct llsd_select_uuid : public std::unary_function<LLSD, LLSD::UUID> +struct llsd_select_uuid { LLSD::UUID operator()(const LLSD& sd) const { return sd.asUUID(); } }; -struct llsd_select_string : public std::unary_function<LLSD, LLSD::String> +struct llsd_select_string { LLSD::String operator()(const LLSD& sd) const { diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h index 2be7112404..e56cf03b45 100644 --- a/indra/llcommon/llsdjson.h +++ b/indra/llcommon/llsdjson.h @@ -34,7 +34,7 @@ #include "stdtypes.h" #include "llsd.h" -#include "value.h" +#include "json/value.h" /// Convert a parsed JSON structure into LLSD maintaining member names and /// array indexes. diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 8b4a0ee6d8..a510b73096 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,6 +34,9 @@ #include <iostream> #include "apr_base64.h" +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> + #ifdef LL_USESYSTEMLIBS # include <zlib.h> #else @@ -2128,7 +2131,9 @@ std::string zip_llsd(LLSD& data) { //copy result into output if (strm.avail_out >= CHUNK) { - free(output); + deflateEnd(&strm); + if(output) + free(output); LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; return std::string(); } @@ -2151,7 +2156,9 @@ std::string zip_llsd(LLSD& data) } else { - free(output); + deflateEnd(&strm); + if(output) + free(output); LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; return std::string(); } @@ -2162,7 +2169,8 @@ std::string zip_llsd(LLSD& data) std::string result((char*) output, size); deflateEnd(&strm); - free(output); + if(output) + free(output); return result; } @@ -2172,53 +2180,66 @@ std::string zip_llsd(LLSD& data) // and deserializes from that copy using LLSDSerialize LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size) { + std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]); + if (!in) + { + return ZR_MEM_ERROR; + } + is.read((char*) in.get(), size); + + return unzip_llsd(data, in.get(), size); +} + +LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size) +{ U8* result = NULL; U32 cur_size = 0; z_stream strm; - const U32 CHUNK = 65536; + constexpr U32 CHUNK = 1024 * 512; - U8 *in = new(std::nothrow) U8[size]; - if (!in) + static thread_local std::unique_ptr<U8[]> out; + if (!out) { - return ZR_MEM_ERROR; + out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]); } - is.read((char*) in, size); - - U8 out[CHUNK]; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = size; - strm.next_in = in; + strm.next_in = const_cast<U8*>(in); S32 ret = inflateInit(&strm); do { strm.avail_out = CHUNK; - strm.next_out = out; + strm.next_out = out.get(); ret = inflate(&strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR) + switch (ret) + { + case Z_NEED_DICT: + case Z_DATA_ERROR: { inflateEnd(&strm); free(result); - delete [] in; return ZR_DATA_ERROR; } - - switch (ret) + case Z_STREAM_ERROR: + case Z_BUF_ERROR: { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; - case Z_DATA_ERROR: + inflateEnd(&strm); + free(result); + return ZR_BUFFER_ERROR; + } + case Z_MEM_ERROR: + { inflateEnd(&strm); free(result); - delete [] in; return ZR_MEM_ERROR; - break; + } } U32 have = CHUNK-strm.avail_out; @@ -2231,17 +2252,15 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, { free(result); } - delete[] in; return ZR_MEM_ERROR; } result = new_result; - memcpy(result+cur_size, out, have); + memcpy(result+cur_size, out.get(), have); cur_size += have; - } while (ret == Z_OK); + } while (ret == Z_OK && ret != Z_STREAM_END); inflateEnd(&strm); - delete [] in; if (ret != Z_STREAM_END) { @@ -2251,37 +2270,11 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, //result now points to the decompressed LLSD block { - std::istringstream istr; - // Since we are using this for meshes, data we are dealing with tend to be large. - // So string can potentially fail to allocate, make sure this won't cause problems - try - { - std::string res_str((char*)result, cur_size); - - std::string deprecated_header("<? LLSD/Binary ?>"); - - if (res_str.substr(0, deprecated_header.size()) == deprecated_header) - { - res_str = res_str.substr(deprecated_header.size() + 1, cur_size); - } - cur_size = res_str.size(); - - istr.str(res_str); - } -#ifdef LL_WINDOWS - catch (std::length_error) - { - free(result); - return ZR_SIZE_ERROR; - } -#endif - catch (std::bad_alloc&) - { - free(result); - return ZR_MEM_ERROR; - } + char* result_ptr = strip_deprecated_header((char*)result, cur_size); - if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH)) + boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size); + + if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH)) { free(result); return ZR_PARSE_ERROR; @@ -2395,4 +2388,22 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 return result; } +char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size) +{ + const char* deprecated_header = "<? LLSD/Binary ?>"; + constexpr size_t deprecated_header_size = 17; + + if (cur_size > deprecated_header_size + && memcmp(in, deprecated_header, deprecated_header_size) == 0) + { + in = in + deprecated_header_size; + cur_size = cur_size - deprecated_header_size; + if (header_size) + { + *header_size = deprecated_header_size + 1; + } + } + + return in; +} diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index d6079fd9fa..d33d2b6f34 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -858,9 +858,12 @@ public: ZR_SIZE_ERROR, ZR_DATA_ERROR, ZR_PARSE_ERROR, + ZR_BUFFER_ERROR, + ZR_VERSION_ERROR } EZipRresult; // return OK or reason for failure static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size); + static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size); }; //dirty little zip functions -- yell at davep @@ -868,4 +871,7 @@ LL_COMMON_API std::string zip_llsd(LLSD& data); LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size); + +// returns a pointer to the array or past the array if the deprecated header exists +LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr); #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index a90c2c7e08..25131291f9 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -142,7 +142,7 @@ struct DeletePairedPointerArray // llselect2nd<map_type::value_type>())); template<typename T> -struct DeletePointerFunctor : public std::unary_function<T*, bool> +struct DeletePointerFunctor { bool operator()(T* ptr) const { @@ -153,7 +153,7 @@ struct DeletePointerFunctor : public std::unary_function<T*, bool> // See notes about DeleteArray for why you should consider avoiding this. template<typename T> -struct DeleteArrayFunctor : public std::unary_function<T*, bool> +struct DeleteArrayFunctor { bool operator()(T* ptr) const { @@ -395,16 +395,17 @@ OutputIter ll_transform_n( // select... with the stl. Look up usage on the sgi website. template <class _Pair> -struct _LLSelect1st : public std::unary_function<_Pair, typename _Pair::first_type> { - const typename _Pair::first_type& operator()(const _Pair& __x) const { +struct _LLSelect1st +{ + const auto& operator()(const _Pair& __x) const { return __x.first; } }; template <class _Pair> -struct _LLSelect2nd : public std::unary_function<_Pair, typename _Pair::second_type> +struct _LLSelect2nd { - const typename _Pair::second_type& operator()(const _Pair& __x) const { + const auto& operator()(const _Pair& __x) const { return __x.second; } }; @@ -416,9 +417,7 @@ template <class _Pair> struct llselect2nd : public _LLSelect2nd<_Pair> {}; // compose... with the stl. Look up usage on the sgi website. template <class _Operation1, class _Operation2> -class ll_unary_compose : - public std::unary_function<typename _Operation2::argument_type, - typename _Operation1::result_type> +class ll_unary_compose { protected: _Operation1 __op1; @@ -426,8 +425,9 @@ protected: public: ll_unary_compose(const _Operation1& __x, const _Operation2& __y) : __op1(__x), __op2(__y) {} - typename _Operation1::result_type - operator()(const typename _Operation2::argument_type& __x) const { + template <typename _Op2Arg> + auto + operator()(const _Op2Arg& __x) const { return __op1(__op2(__x)); } }; @@ -441,8 +441,7 @@ llcompose1(const _Operation1& __op1, const _Operation2& __op2) template <class _Operation1, class _Operation2, class _Operation3> class ll_binary_compose - : public std::unary_function<typename _Operation2::argument_type, - typename _Operation1::result_type> { +{ protected: _Operation1 _M_op1; _Operation2 _M_op2; @@ -451,8 +450,9 @@ public: ll_binary_compose(const _Operation1& __x, const _Operation2& __y, const _Operation3& __z) : _M_op1(__x), _M_op2(__y), _M_op3(__z) { } - typename _Operation1::result_type - operator()(const typename _Operation2::argument_type& __x) const { + template<typename OP2ARG> + auto + operator()(const OP2ARG& __x) const { return _M_op1(_M_op2(__x), _M_op3(__x)); } }; @@ -468,54 +468,51 @@ llcompose2(const _Operation1& __op1, const _Operation2& __op2, // helpers to deal with the fact that MSDev does not package // bind... with the stl. Again, this is from sgi. -template <class _Operation> -class llbinder1st : - public std::unary_function<typename _Operation::second_argument_type, - typename _Operation::result_type> { +template <class _Operation, typename _Arg1> +class llbinder1st +{ protected: _Operation op; - typename _Operation::first_argument_type value; + _Arg1 value; public: - llbinder1st(const _Operation& __x, - const typename _Operation::first_argument_type& __y) + llbinder1st(const _Operation& __x, const _Arg1& __y) : op(__x), value(__y) {} - typename _Operation::result_type - operator()(const typename _Operation::second_argument_type& __x) const { - return op(value, __x); - } + template <typename _Arg2> + auto + operator()(const _Arg2& __x) const { + return op(value, __x); + } }; template <class _Operation, class _Tp> -inline llbinder1st<_Operation> +inline auto llbind1st(const _Operation& __oper, const _Tp& __x) { - typedef typename _Operation::first_argument_type _Arg1_type; - return llbinder1st<_Operation>(__oper, _Arg1_type(__x)); + return llbinder1st<_Operation, _Tp>(__oper, __x); } -template <class _Operation> +template <class _Operation, typename _Arg2> class llbinder2nd - : public std::unary_function<typename _Operation::first_argument_type, - typename _Operation::result_type> { +{ protected: _Operation op; - typename _Operation::second_argument_type value; + _Arg2 value; public: llbinder2nd(const _Operation& __x, - const typename _Operation::second_argument_type& __y) + const _Arg2& __y) : op(__x), value(__y) {} - typename _Operation::result_type - operator()(const typename _Operation::first_argument_type& __x) const { + template <typename _Arg1> + auto + operator()(const _Arg1& __x) const { return op(__x, value); } }; template <class _Operation, class _Tp> -inline llbinder2nd<_Operation> +inline auto llbind2nd(const _Operation& __oper, const _Tp& __x) { - typedef typename _Operation::second_argument_type _Arg2_type; - return llbinder2nd<_Operation>(__oper, _Arg2_type(__x)); + return llbinder2nd<_Operation, _Tp>(__oper, __x); } /** @@ -548,8 +545,7 @@ bool before(const std::type_info* lhs, const std::type_info* rhs) namespace std { template <> - struct less<const std::type_info*>: - public std::binary_function<const std::type_info*, const std::type_info*, bool> + struct less<const std::type_info*> { bool operator()(const std::type_info* lhs, const std::type_info* rhs) const { @@ -558,8 +554,7 @@ namespace std }; template <> - struct less<std::type_info*>: - public std::binary_function<std::type_info*, std::type_info*, bool> + struct less<std::type_info*> { bool operator()(std::type_info* lhs, std::type_info* rhs) const { diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp deleted file mode 100644 index d8a063e8d5..0000000000 --- a/indra/llcommon/llthreadlocalstorage.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file llthreadlocalstorage.cpp - * @author Richard - * @date 2013-1-11 - * @brief implementation of thread local storage utility classes - * - * $LicenseInfo:firstyear=2013&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 "llthreadlocalstorage.h" -#include "llapr.h" - -// -//LLThreadLocalPointerBase -// -bool LLThreadLocalPointerBase::sInitialized = false; - -void LLThreadLocalPointerBase::set( void* value ) -{ - llassert(sInitialized && mThreadKey); - - apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - LL_ERRS() << "Failed to set thread local data" << LL_ENDL; - } -} - -void* LLThreadLocalPointerBase::get() const -{ - // llassert(sInitialized); - void* ptr; - apr_status_t result = - apr_threadkey_private_get(&ptr, mThreadKey); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - LL_ERRS() << "Failed to get thread local data" << LL_ENDL; - } - return ptr; -} - - -void LLThreadLocalPointerBase::initStorage( ) -{ - apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - LL_ERRS() << "Failed to allocate thread local data" << LL_ENDL; - } -} - -void LLThreadLocalPointerBase::destroyStorage() -{ - if (sInitialized) - { - if (mThreadKey) - { - apr_status_t result = apr_threadkey_private_delete(mThreadKey); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - LL_ERRS() << "Failed to delete thread local data" << LL_ENDL; - } - } - } -} - -//static -void LLThreadLocalPointerBase::initAllThreadLocalStorage() -{ - if (!sInitialized) - { - for (auto& base : instance_snapshot()) - { - base.initStorage(); - } - sInitialized = true; - } -} - -//static -void LLThreadLocalPointerBase::destroyAllThreadLocalStorage() -{ - if (sInitialized) - { - //for (auto& base : instance_snapshot()) - //{ - // base.destroyStorage(); - //} - sInitialized = false; - } -} diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h index 3b5786023f..bdd28ec865 100644 --- a/indra/llcommon/llthreadlocalstorage.h +++ b/indra/llcommon/llthreadlocalstorage.h @@ -30,100 +30,6 @@ #include "llinstancetracker.h" -class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase> -{ -public: - LLThreadLocalPointerBase() - : mThreadKey(NULL) - { - if (sInitialized) - { - initStorage(); - } - } - - LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other) - : mThreadKey(NULL) - { - if (sInitialized) - { - initStorage(); - } - } - - ~LLThreadLocalPointerBase() - { - destroyStorage(); - } - - static void initAllThreadLocalStorage(); - static void destroyAllThreadLocalStorage(); - -protected: - void set(void* value); - - void* get() const; - - void initStorage(); - void destroyStorage(); - -protected: - struct apr_threadkey_t* mThreadKey; - static bool sInitialized; -}; - -template <typename T> -class LLThreadLocalPointer : public LLThreadLocalPointerBase -{ -public: - - LLThreadLocalPointer() - {} - - explicit LLThreadLocalPointer(T* value) - { - set(value); - } - - - LLThreadLocalPointer(const LLThreadLocalPointer<T>& other) - : LLThreadLocalPointerBase(other) - { - set(other.get()); - } - - LL_FORCE_INLINE T* get() const - { - return (T*)LLThreadLocalPointerBase::get(); - } - - T* operator -> () const - { - return (T*)get(); - } - - T& operator*() const - { - return *(T*)get(); - } - - LLThreadLocalPointer<T>& operator = (T* value) - { - set((void*)value); - return *this; - } - - bool operator ==(const T* other) const - { - if (!sInitialized) return false; - return get() == other; - } - - bool isNull() const { return !sInitialized || get() == NULL; } - - bool notNull() const { return sInitialized && get() != NULL; } -}; - template<typename DERIVED_TYPE> class LLThreadLocalSingletonPointer { @@ -139,10 +45,10 @@ public: } private: - static LL_THREAD_LOCAL DERIVED_TYPE* sInstance; + static thread_local DERIVED_TYPE* sInstance; }; template<typename DERIVED_TYPE> -LL_THREAD_LOCAL DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL; +thread_local DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL; #endif // LL_LLTHREADLOCALSTORAGE_H diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp index f59b207ded..acdda5fe1e 100644 --- a/indra/llcommon/lltrace.cpp +++ b/indra/llcommon/lltrace.cpp @@ -40,7 +40,7 @@ StatBase::StatBase( const char* name, const char* description ) mDescription(description ? description : "") { #ifndef LL_RELEASE_FOR_DOWNLOAD - if (LLTrace::get_thread_recorder().notNull()) + if (LLTrace::get_thread_recorder() != NULL) { LL_ERRS() << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << LL_ENDL; } diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp index 34299f5a29..fe447d5319 100644 --- a/indra/llcommon/lltraceaccumulators.cpp +++ b/indra/llcommon/lltraceaccumulators.cpp @@ -93,7 +93,7 @@ void AccumulatorBufferGroup::makeCurrent() mStackTimers.makeCurrent(); mMemStats.makeCurrent(); - ThreadRecorder* thread_recorder = get_thread_recorder().get(); + ThreadRecorder* thread_recorder = get_thread_recorder(); AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers; // update stacktimer parent pointers for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++) diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 1613af1dcf..8cbb0db135 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -95,7 +95,7 @@ Recording::~Recording() // allow recording destruction without thread recorder running, // otherwise thread shutdown could crash if a recording outlives the thread recorder // besides, recording construction and destruction is fine without a recorder...just don't attempt to start one - if (isStarted() && LLTrace::get_thread_recorder().notNull()) + if (isStarted() && LLTrace::get_thread_recorder() != NULL) { LLTrace::get_thread_recorder()->deactivate(mBuffers.write()); } @@ -112,9 +112,9 @@ void Recording::update() // must have llassert(mActiveBuffers != NULL - && LLTrace::get_thread_recorder().notNull()); + && LLTrace::get_thread_recorder() != NULL); - if(!mActiveBuffers->isCurrent()) + if(!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL) { AccumulatorBufferGroup* buffers = mBuffers.write(); LLTrace::get_thread_recorder()->deactivate(buffers); @@ -144,7 +144,7 @@ void Recording::handleStart() mSamplingTimer.reset(); mBuffers.setStayUnique(true); // must have thread recorder running on this thread - llassert(LLTrace::get_thread_recorder().notNull()); + llassert(LLTrace::get_thread_recorder() != NULL); mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write()); #endif } @@ -155,7 +155,7 @@ void Recording::handleStop() #if LL_TRACE_ENABLED mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); // must have thread recorder running on this thread - llassert(LLTrace::get_thread_recorder().notNull()); + llassert(LLTrace::get_thread_recorder() != NULL); LLTrace::get_thread_recorder()->deactivate(mBuffers.write()); mActiveBuffers = NULL; mBuffers.setStayUnique(false); @@ -1181,8 +1181,8 @@ void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& oth PeriodicRecording& get_frame_recording() { - static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED)); - return *sRecording; + static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED); + return sRecording; } } diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 090d3297a0..26db15eaa0 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -308,13 +308,13 @@ ThreadRecorder* get_master_thread_recorder() return sMasterThreadRecorder; } -LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr() +ThreadRecorder*& get_thread_recorder_ptr() { - static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder; + static thread_local ThreadRecorder* s_thread_recorder; return s_thread_recorder; } -const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder() +ThreadRecorder* get_thread_recorder() { return get_thread_recorder_ptr(); } diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h index a797c6687e..8fd1e5ef58 100644 --- a/indra/llcommon/lltracethreadrecorder.h +++ b/indra/llcommon/lltracethreadrecorder.h @@ -32,7 +32,6 @@ #include "llmutex.h" #include "lltraceaccumulators.h" -#include "llthreadlocalstorage.h" namespace LLTrace { @@ -92,7 +91,7 @@ namespace LLTrace }; - const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder(); + ThreadRecorder* get_thread_recorder(); void set_thread_recorder(ThreadRecorder*); void set_master_thread_recorder(ThreadRecorder*); diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index acce8366ea..6f9e09a587 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -1009,36 +1009,6 @@ LLUUID::LLUUID() return !(word[0] | word[1] | word[2] | word[3]); } -// Copy constructor - LLUUID::LLUUID(const LLUUID& rhs) -{ - U32 *tmp = (U32 *)mData; - U32 *rhstmp = (U32 *)rhs.mData; - tmp[0] = rhstmp[0]; - tmp[1] = rhstmp[1]; - tmp[2] = rhstmp[2]; - tmp[3] = rhstmp[3]; -} - - LLUUID::~LLUUID() -{ -} - -// Assignment - LLUUID& LLUUID::operator=(const LLUUID& rhs) -{ - // No need to check the case where this==&rhs. The branch is slower than the write. - U32 *tmp = (U32 *)mData; - U32 *rhstmp = (U32 *)rhs.mData; - tmp[0] = rhstmp[0]; - tmp[1] = rhstmp[1]; - tmp[2] = rhstmp[2]; - tmp[3] = rhstmp[3]; - - return *this; -} - - LLUUID::LLUUID(const char *in_string) { if (!in_string || in_string[0] == 0) diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index 86a396ab06..c139c4eb4e 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -55,10 +55,7 @@ public: LLUUID(); explicit LLUUID(const char *in_string); // Convert from string. explicit LLUUID(const std::string& in_string); // Convert from string. - LLUUID(const LLUUID &in); - LLUUID &operator=(const LLUUID &rhs); - - ~LLUUID(); + ~LLUUID() = default; // // MANIPULATORS @@ -131,6 +128,9 @@ public: U8 mData[UUID_BYTES]; }; +static_assert(std::is_trivially_copyable<LLUUID>::value, "LLUUID must be trivial copy"); +static_assert(std::is_trivially_move_assignable<LLUUID>::value, "LLUUID must be trivial move"); +static_assert(std::is_standard_layout<LLUUID>::value, "LLUUID must be a standard layout type"); typedef std::vector<LLUUID> uuid_vec_t; typedef std::set<LLUUID> uuid_set_t; diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h index 12df693910..c0b13135f9 100644 --- a/indra/llcommon/stringize.h +++ b/indra/llcommon/stringize.h @@ -30,7 +30,7 @@ #define LL_STRINGIZE_H #include <sstream> -#include <llstring.h> +#include "llstring.h" #include <boost/call_traits.hpp> /** diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index daa84df792..7ee36a9ea6 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -525,7 +525,7 @@ namespace tut result.ensure(); } - struct TestLargeMessage: public std::binary_function<size_t, size_t, bool> + struct TestLargeMessage { TestLargeMessage(const std::string& PYTHON_, const std::string& reader_module_, const std::string& test_name_): diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h index 3e0da94c02..0c3a541196 100644 --- a/indra/llcommon/threadsafeschedule.h +++ b/indra/llcommon/threadsafeschedule.h @@ -248,7 +248,7 @@ namespace LL TimePoint until = TimePoint::clock::now() + std::chrono::hours(24); pop_result popped = tryPopUntil_(lock, until, tt); if (popped == POPPED) - return std::move(tt); + return tt; // DONE: throw, just as super::pop() does if (popped == DONE) |