summaryrefslogtreecommitdiff
path: root/indra/llcommon
AgeCommit message (Collapse)Author
2021-11-23SL-16094: Tweak llstring mergeNat Goodspeed
2021-11-23SL-16094: Merge llstring work from SL-16207Nat Goodspeed
2021-11-23SL-16094: Extend stringize() to support variadic arguments.Nat Goodspeed
It's useful to be able to say STRINGIZE(item0 << item1 << item2), and we use that a lot in our code base. But weird syntax aside, there are a couple advantages to being able to write stringize(item0, item1, item2). First, it allows stringize() to be used from within some other variadic function, without having to make that function a macro that accepts an arbitrary insertion-operator expression. There's no such thing as a member macro. Second, particularly for variadic functions, it allows us to optimize the single-argument case stringize(item0). A macro can't do that. When item0 is already a string of the desired char type, instead of streaming it into a std::ostringstream and retrieving it again, we can simply return the input string. When it's a pointer to the desired char type, we can directly construct the result string without the help of std::ostringstream. When it's a string of some other char type, we can engage ll_convert() to perform needed conversions. We generalize and optimize the generic gstringize() function, retaining the role of stringize() and wstringize() as thin wrappers that merely provide the desired char type. Optimizing the single-argument case requires separately defining gstringize() with two or more arguments: the general case. Then gstringize(arg) is delegated to a gstringize_impl class template so we can partially specialize to recognize a std::basic_string<desired_char_type> argument, as well as desired_char_type*. Both these specializations engage ll_convert(), which already handles the trivial case when no conversion is required. Use of ll_convert() in this role supercedes and generalizes the previous wstring_to_utf8str() and utf8str_to_wstring() overloads. Also introduce stream_to(std::ostream&, ...) to support variadic streaming to other destinations, e.g. a file, std::cout, ...
2021-11-19SL-16329 - track frame time and jitter (as average deviation frame to frame) ↵Brad Payne (Vir Linden)
in stats window
2021-11-19SL-16094: Stylish braces!Nat Goodspeed
2021-11-10SL-16094: Add WorkQueue::size() method to support changeset 08336bb.Nat Goodspeed
We want to skip calling PostMessage() to bump the window thread out of GetMessage() in any frame with no work functions pending for that thread. That test depends on being able to sense the size() of the queue. Having converted to WorkQueue, we need that queue to support size().
2021-11-05SL-16202: Use WorkQueue::postTo() for texture create/post handshake.Nat Goodspeed
That is, when LLViewerFetchedTexture::scheduleCreateTexture() wants to call createTexture() on the LLImageGLThread, but postCreateTexture() on the main thread, use the "mainloop" WorkQueue to set up the handshake. Give ThreadPool a public virtual run() method so a subclass can override with desired behavior. This necessitates a virtual destructor. Add accessors for embedded WorkQueue (for post calls), ThreadPool name and width (in threads). Allow LLSimpleton::createInstance() to forward arguments to the subject constructor. Make LLImageGLThread an LLSimpleton - that abstraction didn't yet exist at the time LLImageGLThread was coded. Also derive from ThreadPool rather than LLThread. Make it a single-thread "pool" with a very large queue capacity.
2021-11-04SL-16202: Use large WorkQueue size limits for mainloop and General.Nat Goodspeed
Give ThreadPool and WorkQueue the ability to override default ThreadSafeSchedule capacity. Instantiate "mainloop" WorkQueue and "General" ThreadPool with very large capacity because we never want to have to block trying to push to either.
2021-11-04SL-16202: Add postIfOpen() methods to WorkQueue, LLThreadSafeQueue.Nat Goodspeed
postIfOpen() provides a no-exception alternative to post(), which blocks if full but throws if closed. postIfOpen() likewise blocks if full, but returns true if able to post and false if the queue was closed.
2021-11-04SL-16202: Instantiate LLSimpleton::sInstance genericallyNat Goodspeed
instead of requiring a separate declaration for each subclass. The previous way produces errors in clang.
2021-11-04SL-16202: Merge branch 'sl-16220' into glthreadNat Goodspeed
2021-11-02SL-16207: Fix bug in ll_convert_string_to_utf8_string().Nat Goodspeed
That function wants to pass a code_page to ll_convert_string_to_wide(), but the code_page parameter was being mistaken for the length parameter, leading to access violations.
2021-11-02SL-16207: Guess Microsoft compiler isn't smart about default params?Nat Goodspeed
clang allows us to specify, as a default function parameter, an expression involving a preceding parameter, e.g. (char* ptr, size_t len=strlen(ptr)). The Microsoft compiler produces errors, requiring more overloads to address that. Also #undef llstring.h's declaration helper macros at the bottom of the file. Once we've used them to declare stuff, they need not (should not) be visible to the consuming source file.
2021-11-02SL-16207: Create uniform overload sets for wide-string conversions.Nat Goodspeed
Use new ll_convert_forms() macro in llstring.h to declare, for each wide-string conversion function of interest, four overloads. The real one, the nontrivial one, is (const char*, size_t len), implemented in llstring.cpp. Then (const string&, size_t len), (const char*) and (const string&) are each trivially implemented with an inline call to (const char*, size_t len). Notably, we change all S32 len parameters to size_t. Using S32 is old skool. Tweak each nontrivial implementation in llstring.cpp to accept (const char*, size_t len) instead of (const string&) with or without explicit length. Eliminate from llstring.cpp trivial overloads (deriving length from either a const char* or from a string), since those are now inline in the header. Of course three of those overloads will be unified once we enable C++17 and change each relevant parameter to std::string_view, but we're not yet there. Meanwhile, this suite of overloads minimizes, to the best of our ability, new string allocations solely for parameter passing. And use of a macro means we need only change the macro once we get std::string_view. We take this step because some use cases require (const char*), some require (const string&, size_t len), others (const char*, size_t len) ... We were missing some key overloads, and had to work around them by instantiating new string objects (necessitating both allocation and character copying) just to pass the desired parameter. Using the macro ensures this consistent set of overloads for every wide-string conversion function. Additionally, knowing that the ugly-name overloads exist, ll_convert_forms() implicitly defines corresponding ll_convert<TARGET>() overloads. Streamline declarations of utf16str_to_wstring(), wstring_to_utf16str(), utf8str_to_utf16str(), utf16str_to_utf8str(), utf8str_to_wstring(), wstring_to_utf8str(), ll_convert_wide_to_wstring() and ll_convert_wstring_to_wide() using ll_convert_forms(). Use corresponding new ll_convert_cp_forms() macro to declare consistent overloads for conversion functions accepting an optional unsigned int code_page parameter. We used to delegate to the .cpp file the implementation of each overload accepting code_page so llstring.h need not include the Windows header defining the CP_UTF8 default; this is more simply accomplished by introducing a small ll_wstring_default_code_page() function to retrieve it from the .cpp file. That lets us specify the code_page parameter as optional, using that function as its default value. Use ll_convert_cp_forms() to streamline declarations of ll_convert_wide_to_string() and ll_convert_string_to_wide(). Introduce real implementations of ll_convert_wide_to_wstring() and ll_convert_wstring_to_wide(). The previous implementations merely copied individual characters, which is wrong: when we convert UTF16LE to UTF32, we can and should fold multi-character UTF16LE encodings to the corresponding single UTF32 character. The real implemenations leverage our awareness that both llutf16string and Windows std::wstring (either variant) use UTF16LE encoding, so we can reuse the corresponding llutf16string conversions. Introduce generic ll_convert_length() function, specialized as either std::strlen() or std::wcslen() depending on parameter type. (Even if std::wcslen() is derived from classic C, why doesn't the C++ standard library define a std::strlen(const wchar_t*) overload to call it?) Fix ll_convert_alias()'s ll_convert_impl specialization's operator() to accept boost::call_traits::param_type, so we can pass (e.g.) const std::wstring& but also const wchar_t* instead of const wchar_t*&.
2021-11-01SL-16237 FIXED Viewer hangs on loginMnikolenko Productengine
2021-10-28SL-16148 SL-16244 SL-16270 SL-16253 Remove most BlockTimers, remove ↵Dave Parks
LLMemTracked, introduce alignas, hook most/all reamining allocs, disable synchronous occlusion, and convert frequently accessed LLSingletons to LLSimpleton
2021-10-27SL-16220: Add tests for WorkQueue::waitForResult(), void & non-void.Nat Goodspeed
2021-10-27SL-16207: Update llstring.h handling of different string types.Nat Goodspeed
In llpreprocessor.h, consider the case of clang on Windows: #define LL_WCHAR_T_NATIVE there as well as for the Microsoft compiler with /Zc:wchar_t switch. In stdtypes.h, inject a LLWCHAR_IS_WCHAR_T symbol to allow the preprocessor to make decisions about when the types are identical. llstring.h's conversion logic deals with three types of wide strings (LLWString, std::wstring and utf16string) based on three types of wide char (llwchar, wchar_t and U16, respectively). Sometimes they're three distinct types, sometimes wchar_t is identical to llwchar and sometimes wchar_t is identical to U16. Rationalize the three cases using ll_convert_u16_alias() and new ll_convert_wstr_alias() macros. stringize.h was directly calling wstring_to_utf8str() and utf8str_to_wstring(), which was producing errors with VS 2019 clang since there isn't actually a wstring_to_utf8str(std::wstring) overload. Use ll_convert<std::string>() instead, since that redirects to the relevant ll_convert_wide_to_string() function. (And now you see why we've been trying to migrate to the uniform ll_convert<target>() wrapper!) Similarly, call ll_convert<std::wstring>() instead of a two-step conversion from utf8str_to_wstring(), producing LLWString, then a character-by-character copy from LLWString to std::wstring. That isn't even correct: on Windows, we should be encoding from UTF32 to UTF16.
2021-10-26SL-16220: Make WorkQueue::postTo() return exception to caller.Nat Goodspeed
postTo() sets up two-way communication: the caller asks to run work on some other WorkQueue, expecting an eventual callback on the originating WorkQueue. That permits us to transport any exception thrown by the work callable back to rethrow on the originating WorkQueue.
2021-10-26SL-16220: Change WorkQueue::runOn() to waitForResult().Nat Goodspeed
In addition to the name making the blocking explicit, we changed the signature: instead of specifying a target WorkQueue on which to run, waitForResult() runs the passed callable on its own WorkQueue. Why is that? Because, unlike postTo(), we do not require a handshake between two different WorkQueues. postTo() allows running arbitrary callback code, setting variables or whatever, on the originating WorkQueue (presumably on the originating thread). waitForResult() synchronizes using Promise/Future, which are explicitly designed for cross-thread communication. We need not call set_value() on the originating thread, so we don't need a postTo() callback lambda.
2021-10-26SL-16243 Followup -- fix for inconsistently calling TracyAlloc/TracyFreeRunitai Linden
2021-10-26SL-16193 Fix for mesh selection outline not rendering correctly (and broken ↵Dave Parks
physics shapes display).
2021-10-25SL-16220: WorkQueue::runOn() methods submit work, wait for result.Nat Goodspeed
The idea is that you can call runOn(target, callable) from a (non-default) coroutine and block that coroutine until the result becomes available. As a safety check, we forbid calling runOn() from a thread's default coroutine, assuming that a given thread's default coroutine is the one servicing the relevant WorkQueue.
2021-10-25SL-16243 Add Tracy timers to global new/delete overrides.Dave Parks
2021-10-25SL-16220: Specialize WorkQueue for callable with void return.Nat Goodspeed
Add a test exercising this feature.
2021-10-25Merged DRTVWR-546 into SL-15999Vir Linden
2021-10-22SL-16220: Fix thread name expression.Nat Goodspeed
2021-10-22SL-16203 Fix for wonky handling of mouse deltas.Dave Parks
2021-10-22SL-16220: Merge branch 'master' into sl-16220Nat Goodspeed
2021-10-22SL-16220: Add LL::ThreadPool class and a "General" instance.Nat Goodspeed
ThreadPool bundles a WorkQueue with the specified number of worker threads to service it. Each ThreadPool has a name that can be used to locate its WorkQueue. Each worker thread calls WorkQueue::runUntilClose(). ThreadPool listens on the "LLApp" LLEventPump for shutdown notification. On receiving that, it closes its WorkQueue and then join()s each of its worker threads for orderly shutdown. Add a settings.xml entry "ThreadPoolSizes", the first LLSD-valued settings entry to expect a map: pool name->size. The expectation is that usually code instantiating a particular ThreadPool will have a default size in mind, but it should check "ThreadPoolSizes" for a user override. Make idle_startup()'s STATE_SEED_CAP_GRANTED state instantiate a "General" ThreadPool. This is function-static for lazy initialization. Eliminate LLMainLoopRepeater, which is completely unreferenced. Any potential future use cases are better addressed by posting to the main loop's WorkQueue. Eliminate llappviewer.cpp's private LLDeferredTaskList class, which implemented LLAppViewer::addOnIdleCallback(). Make addOnIdleCallback() post work to the main loop's WorkQueue instead.
2021-10-21SL-16202 Fix for textures appearing black or flashing white due to ↵Dave Parks
optimization bugs.
2021-10-20Merge branch 'DRTVWR-546' of ssh://bitbucket.org/lindenlab/viewer into ↵Brad Payne (Vir Linden)
DRTVWR-546
2021-10-19SL-16197 Optimize LLEnvironment handling of shader uniforms. Instrument ↵Dave Parks
LLSD. Enable Fast Timers when Tracy is enabled to catch Fast Timer overhead.
2021-10-15Merge branch 'DRTVWR-546' of ssh://bitbucket.org/lindenlab/viewer into ↵Brad Payne (Vir Linden)
DRTVWR-546
2021-10-14SL-16131 Fix for alignment warnings on Win32 builds.Dave Parks
2021-10-13Merge branch 'master' v6.4.24 into DRTVWR-546Dave Houlton
2021-10-11SL-16099 Multi-threaded OpenGL usage on Windows, enable Core Profile and ↵Dave Parks
VAOs by default.
2021-10-08Merge branch 'SL-16024' into DRTVWR-546Nat Goodspeed
2021-10-08SL-16024: Resolve bizarre VS compile error. Thanks Callum!Nat Goodspeed
It seems CALLBACK is a macro in some Microsoft header file. Bleah.
2021-10-07SL-16024: Merge branch 'SL-16024' into SL-16024-to-546Nat Goodspeed
2021-10-07SL-16024: Defend against two threads making "anonymous" WorkQueues.Nat Goodspeed
Also make workqueue_test.cpp more robust.
2021-10-07SL-16024: Merge branch 'DRTVWR-546' into SL-16024-to-546Nat Goodspeed
2021-10-07SL-16024: Add LL::WorkQueue for passing work items between threads.Nat Goodspeed
A typical WorkQueue has a string name, which can be used to find it to post work to it. "Work" is a nullary callable. WorkQueue is a multi-producer, multi-consumer thread-safe queue: multiple threads can service the WorkQueue, multiple threads can post work to it. Work can be scheduled in the future by submitting with a timestamp. In addition, a given work item can be scheduled to run on a recurring basis. A requesting thread servicing a WorkQueue of its own, such as the viewer's main thread, can submit work to another WorkQueue along with a callback to be passed the result (of arbitrary type) of the first work item. The callback is posted to the originating WorkQueue, permitting safe data exchange between participating threads. Methods are provided for different kinds of servicing threads. runUntilClose() is useful for a simple worker thread. runFor(duration) devotes no more than a specified time slice to that WorkQueue, e.g. for use by the main thread.
2021-10-07SL-16024: Make LLCond::get() lock and return by value.Nat Goodspeed
Its previous behavior, returning a const reference without locking, was wrong: it could return a reference to an object in an inconsistent state if it was concurrently being modified on another thread. Locking the mutex and returning a copy by value is the correct behavior.
2021-10-07SL-16024: Adapt llinstancetracker_test.cpp to getInstance() change.Nat Goodspeed
2021-10-07SL-16024: Return shared_ptr from LLInstanceTracker::getInstance().Nat Goodspeed
It feels wrong to return a dumb LLInstanceTracker subclass* from getInstance() when we use std::shared_ptr and std::weak_ptr internally. But tweak consumers to use 'auto' or LLInstanceTracker::ptr_t in case we later revisit this decision. We did add a couple get() calls where it's important to obtain a dumb pointer.
2021-10-06SL-16024: Work around VS bug regarding base-class enum.Nat Goodspeed
2021-10-06SL-16024: Fix ThreadSafeSchedule::tryPopFor(), tryPopUntil().Nat Goodspeed
ThreadSafeSchedule::tryPopUntil() (and therefore tryPopFor()) was simply delegating to LLThreadSafeQueue::tryPopUntil(), with an adjusted timeout since we want to wake up as soon as the head item, if any, becomes ready. But then we have to loop back to retry the pop to actually deal with that head item. In addition, ThreadSafeSchedule::popWithTime() was spinning rather than properly blocking on a timed condition variable. Fixed.
2021-10-05SL-16024: Add ThreadSafeSchedule, a timestamped LLThreadSafeQueue.Nat Goodspeed
ThreadSafeSchedule orders its items by timestamp, which can be passed either implicitly or explicitly. The timestamp specifies earliest delivery time: an item cannot be popped until that time. Add initial tests. Tweak the LLThreadSafeQueue base class to support ThreadSafeSchedule: introduce virtual canPop() method to report whether the current head item is available to pop. The base class unconditionally says yes, ThreadSafeSchedule says it depends on whether its timestamp is still in the future. This replaces the protected pop_() overload accepting a predicate. Rather than explicitly passing a predicate through a couple levels of function call, use canPop() at the level it matters. Runtime behavior that varies depending on an object's leaf class is what virtual functions were invented for. Give pop_() a three-state enum return so pop() can distinguish between "closed and empty" (throws exception) versus "closed, not yet drained because we're not yet ready to pop the head item" (waits). Also break out protected tryPopUntil_() method, the body logic of tryPopUntil(). The public method locks the data structure, the protected method requires that its caller has already done so. Add chrono.h with a more full-featured LL::time_point_cast() function than the one found in <chrono>, which only converts between time_point durations, not between time_points based on different clocks.
2021-10-04SL-16024: Don't use a lambda as default arg for universal reference.Nat Goodspeed
Instead, break out a separate pop_() method that explicitly provides the lambda to the real pop_() implementation.