Commit Graph

19 Commits (a3d6544be07e3cd0bb7e4cb78564a0d6077fd910)

Author SHA1 Message Date
Andrey Lihatskiy 1b68f71348 #824 Process source files in bulk: replace tabs with spaces, convert CRLF to LF, and trim trailing whitespaces as needed 2024-04-29 07:56:09 +03:00
Nat Goodspeed f728808d93 SL-19690: Fix a lingering reference to WorkSchedule::postIfOpen() 2023-05-08 12:45:27 -04:00
Nat Goodspeed 026ef1935d SL-19690: Follow up on Rye Mutt's fix for shutdown crashes.
Rather than continuing to propagate try/catch (Closed)
(aka LLThreadSafeQueueInterrupt) constructs through the code base, make
WorkQueueBase::post() return bool indicating success (i.e. ! isClosed()).
This obviates postIfOpen(), which no one was using anyway.

In effect, postIfOpen() is renamed post(), bypassing the exception when
isClosed().

Review existing try/catch blocks of that sort, changing to test for post()
returning false.
2023-05-08 12:07:31 -04:00
Nat Goodspeed fc424a0db9 SL-18809: Add WorkSchedule; remove timestamps from WorkQueue.
For work queues that don't need timestamped tasks, eliminate the overhead of a
priority queue ordered by timestamp. Timestamped task support moves to
WorkSchedule. WorkQueue is a simpler queue that just waits for work.

Both WorkQueue and WorkSchedule can be accessed via new WorkQueueBase API. Of
course the WorkQueueBase API doesn't deal with timestamps, but a WorkSchedule
can be accessed directly to post timestamped tasks and then handled normally
(e.g. by ThreadPool) to run them.

Most ThreadPool functionality migrates to new ThreadPoolBase class, with
template subclass ThreadPoolUsing<WorkQueue> or ThreadPoolUsing<WorkSchedule>
depending on need. ThreadPool is now an alias for ThreadPoolUsing<WorkQueue>.
Importantly, ThreadPoolUsing::getQueue() delivers a reference to the specific
queue subclass type, so you can post timestamped tasks on a queue retrieved
from ThreadPoolUsing<WorkSchedule>::getQueue().

Since ThreadPool is no longer a simple class but an alias for a particular
template specialization, introduce threadpool_fwd.h to forward-declare it.

Recast workqueue_test.cpp to exercise WorkSchedule, since some of the tests
are time-based. A future todo would be to exercise each applicable test with
both WorkQueue and WorkSchedule.
2022-12-09 13:21:45 -05:00
Ptolemy b504c69255 SL-16606: Add profiler category THREAD 2022-01-14 11:50:21 -08:00
Nat Goodspeed 0b066539fe DRTVWR-546, SL-16220, SL-16094: Undo previous glthread branch revert.
Reverting a merge is sticky: it tells git you never want to see that branch
again. Merging the DRTVWR-546 branch, which contained the revert, into the
glthread branch undid much of the development work on that branch. To restore
it we must revert the revert.

This reverts commit 029b41c041.
2021-11-24 10:47:54 -05:00
Nat Goodspeed 78d837789a SL-16400: Make WorkQueue::runFor() and runUntil() stop when done.
runFor(interval) and runUntil(timestamp) are intended, and documented, to run
*no longer than* the specified time. Instead, the initial implementation
always waited the full specified time, hoping for work to arrive. Fix that:
once we clear work that's already pending, return right away.
2021-11-24 09:43:37 -05:00
Nat Goodspeed d71e0a6d47 SL-16094, SL-16400: Merge branch 'DRTVWR-546' into glthread 2021-11-23 21:23:45 -05:00
Runitai Linden cc34e26ef7 SL-16094 Add WorkQueue profile hooks 2021-11-22 11:51:03 -06:00
Dave Houlton 029b41c041 Revert "SL-16220: Merge branch 'origin/DRTVWR-546' into glthread"
This reverts commit 5188a26a85, reversing
changes made to 819088563e.
2021-11-15 09:25:35 -07:00
Nat Goodspeed df8e17d8e8 SL-16094: Add WorkQueue::size() method to support changeset 08336bb.
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-10 10:13:38 -05:00
Nat Goodspeed 834e7ca088 SL-16202: Use large WorkQueue size limits for mainloop and General.
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-04 17:18:57 -04:00
Nat Goodspeed 7a5b921995 SL-16202: Merge branch 'sl-16220' into glthread 2021-11-04 15:40:30 -04:00
Nat Goodspeed e6eebea8da SL-16220: Change WorkQueue::runOn() to waitForResult().
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-26 11:49:53 -04:00
Nat Goodspeed 023d39963e SL-16220: WorkQueue::runOn() methods submit work, wait for result.
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-25 17:31:27 -04:00
Nat Goodspeed 11afa09ea3 SL-16220: Add LL::ThreadPool class and a "General" instance.
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-22 11:36:31 -04:00
Dave Parks e774bffb28 SL-16202 Fix for textures appearing black or flashing white due to optimization bugs. 2021-10-21 21:19:48 +00:00
Nat Goodspeed c585ddb75e SL-16024: Defend against two threads making "anonymous" WorkQueues.
Also make workqueue_test.cpp more robust.
2021-10-07 16:45:15 -04:00
Nat Goodspeed 623ac79120 SL-16024: Add LL::WorkQueue for passing work items between threads.
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-07 15:32:51 -04:00