summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt75
-rw-r--r--indra/llcommon/apply.h115
-rw-r--r--indra/llcommon/llapp.cpp43
-rw-r--r--indra/llcommon/llprocess.cpp8
-rw-r--r--indra/llcommon/llsd.h12
-rw-r--r--indra/llcommon/llsdjson.h2
-rw-r--r--indra/llcommon/llstl.h81
-rw-r--r--indra/llcommon/stringize.h2
-rw-r--r--indra/llcommon/tests/llleap_test.cpp14
9 files changed, 187 insertions, 165 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 108149b5f7..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
@@ -271,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)
@@ -327,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/apply.h b/indra/llcommon/apply.h
new file mode 100644
index 0000000000..7c58d63bc0
--- /dev/null
+++ b/indra/llcommon/apply.h
@@ -0,0 +1,115 @@
+/**
+ * @file apply.h
+ * @author Nat Goodspeed
+ * @date 2022-06-18
+ * @brief C++14 version of std::apply()
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_APPLY_H)
+#define LL_APPLY_H
+
+#include <boost/type_traits/function_traits.hpp>
+#include <tuple>
+
+namespace LL
+{
+
+/**
+ * USAGE NOTE:
+ * https://stackoverflow.com/a/40523474/5533635
+ *
+ * If you're trying to pass apply() a variadic function, the compiler
+ * complains that it can't deduce the callable type, presumably because it
+ * doesn't know which arity to reify to pass.
+ *
+ * But it works to wrap the variadic function in a generic lambda, e.g.:
+ *
+ * @CODE
+ * LL::apply(
+ * [](auto&&... args)
+ * {
+ * return variadic(std::forward<decltype(args)>(args)...);
+ * },
+ * args);
+ * @ENDCODE
+ *
+ * Presumably this is because there's only one instance of the generic lambda
+ * @em type, with a variadic <tt>operator()()</tt>.
+ *
+ * It's pointless to provide a wrapper @em function that implicitly supplies
+ * the generic lambda. You couldn't pass your variadic function to our wrapper
+ * function, for the same original reason!
+ *
+ * Instead we provide a wrapper @em macro. Sorry, Dr. Stroustrup.
+ */
+#define VAPPLY(FUNC, ARGS) \
+ LL::apply( \
+ [](auto&&... args) \
+ { \
+ return (FUNC)(std::forward<decltype(args)>(args)...); \
+ }, \
+ (ARGS))
+
+#if __cplusplus >= 201703L
+
+// C++17 implementation
+using std::apply;
+
+#else // C++14
+
+// Derived from https://stackoverflow.com/a/20441189
+// and https://en.cppreference.com/w/cpp/utility/apply
+template <typename CALLABLE, typename TUPLE, std::size_t... I>
+auto apply_impl(CALLABLE&& func, TUPLE&& args, std::index_sequence<I...>)
+{
+ // call func(unpacked args)
+ return std::forward<CALLABLE>(func)(std::move(std::get<I>(args))...);
+}
+
+template <typename CALLABLE, typename... ARGS>
+auto apply(CALLABLE&& func, const std::tuple<ARGS...>& args)
+{
+ // std::index_sequence_for is the magic sauce here, generating an argument
+ // pack of indexes for each entry in args. apply_impl() can then pass
+ // those to std::get() to unpack args into individual arguments.
+ return apply_impl(std::forward<CALLABLE>(func),
+ args,
+ std::index_sequence_for<ARGS...>{});
+}
+
+// per https://stackoverflow.com/a/57510428/5533635
+template <typename CALLABLE, typename T, size_t SIZE>
+auto apply(CALLABLE&& func, const std::array<T, SIZE>& args)
+{
+ return apply(std::forward<CALLABLE>(func), std::tuple_cat(args));
+}
+
+// per https://stackoverflow.com/a/28411055/5533635
+template <typename CALLABLE, typename T, std::size_t... I>
+auto apply_impl(CALLABLE&& func, const std::vector<T>& args, std::index_sequence<I...>)
+{
+ return apply_impl(std::forward<CALLABLE>(func),
+ std::make_tuple(std::forward<T>(args[I])...),
+ I...);
+}
+
+// this goes beyond C++17 std::apply()
+template <typename CALLABLE, typename T>
+auto apply(CALLABLE&& func, const std::vector<T>& args)
+{
+ constexpr auto arity = boost::function_traits<CALLABLE>::arity;
+ assert(args.size() == arity);
+ return apply_impl(std::forward<CALLABLE>(func),
+ args,
+ std::make_index_sequence<arity>());
+}
+
+#endif // C++14
+
+} // namespace LL
+
+#endif /* ! defined(LL_APPLY_H) */
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index c658075a31..d839b19c99 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/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 92a1fc58a5..cdb9a7ed8a 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -441,42 +441,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/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/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 9754353ab0..7ee36a9ea6 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -15,10 +15,10 @@
#include "llleap.h"
// STL headers
// std headers
+#include <functional>
// external library headers
#include <boost/assign/list_of.hpp>
#include <boost/phoenix/core/argument.hpp>
-#include <boost/foreach.hpp>
// other Linden headers
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
@@ -29,7 +29,6 @@
#include "llstring.h"
#include "stringize.h"
#include "StringVec.h"
-#include <functional>
using boost::assign::list_of;
@@ -110,11 +109,6 @@ namespace tut
"import os\n"
"import sys\n"
"\n"
- // Don't forget that this Python script is written to some
- // temp directory somewhere! Its __file__ is useless in
- // finding indra/lib/python. Use our __FILE__, with
- // raw-string syntax to deal with Windows pathnames.
- "mydir = os.path.dirname(r'" << __FILE__ << "')\n"
"from llbase import llsd\n"
"\n"
"class ProtocolError(Exception):\n"
@@ -241,9 +235,9 @@ namespace tut
"import sys\n"
"sys.stderr.write('''Hello from Python!\n"
"note partial line''')\n");
+ StringVec vcommand{ PYTHON, script.getName() };
CaptureLog log(LLError::LEVEL_INFO);
- waitfor(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName()))));
+ waitfor(LLLeap::create(get_test_name(), vcommand));
log.messageWith("Hello from Python!");
log.messageWith("note partial line");
}
@@ -531,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_):