A tool to synchronize objects:
Objects derived from AISyncClient can signal that they are
'ready' or 'not ready' for up to 32 events (using a bitmask)
at a time. Clients that are created at roughly the same time
as other clients, and which return the same 'key' (a virtual
function returning an AISyncKey object) will be grouped together
and receive events (by means of virtual functions being called)
to notify them of all clients being ready or not for one of the
events (the least significant bit)). The other events can be polled.
This new version does away with all the templates and explicitly
remembers what events each client is ready for instead of just
updating a counter of the number of clients. This was necessary
because a client is removed then the server needs to know if it
was ready or not when it has to be able to update those counters.
This time I chose to just run over all stored clients and AND
and OR the per-client-ready-masks because 1) that information
is available now and 2) the lists will normally contain only
one or two clients, so it's fast enough.
The new version also allows for real key comparison (and derived
keys) instead of just using "hash" value that is compared.
A tool to synchronize objects:
Objects derived from AISyncClient can signal that they are
'ready' or 'not ready' for up to 4 events (using a bitmask)
at a time. Clients that signal to be ready for anything
at roughly the same time as other clients, and which return
the same 'hash' (a virtual function returning a 64bit value)
will be grouped together and receive events (by means of
virtual functions being called) to notify them of all clients
being ready or not for one of the events (syncevent1).
The other three events can be polled.
The memory usage is low (one pointer per client that points
to its AISyncServer object), servers are released to a cache
after about 100 ms (unless there is actual need for synchronization),
so there aren't much of those either.
The CPU usage is extremely low: all events are handled in
parallel in a 32 bit value (6 bits per event to count the
number of registered clients and the number of ready clients
for each event, and the remaining 8 bits to count the
number of reference pointers (which should only be a constant
higher, so that is overkill). To signal to a server that
a client has become ready or not is mostly a function call,
which then takes 1 clock cycle or so before returning.
Registration of a client is slightly more expensive as it
requires a pointer to be added to the end of a std::list.
This tool could easily be used as part of the graphics engine
(not that I intend to do that :p).
Although only used in Debug mode, this showed up in a profiling
with a very significant amount of CPU cycles (in a state when
the viewer bogged down to 1 FPS because of drawing terrain,
but still - significant compared to the code that was being
executed (ie, 10%)).
This patch should bring that down from a few hunderd to one clock
cycle.
This makes LLStringUtil thread-safe by removing a rather unnecessary
LLFastTimer from LLStringUtil::format.
Same thing for LLTrans::getString and LLTrans::findString, where
even a comment stated that the author wasn't interested in measuring
cpu time at all. In this case I added some code back to make sure
that we're not calling LLTrans::getString() in an inner loop, which
was the reason that the LLFastTimer was added.
Made one string static to avoid 45000 look ups during login, which
kinda triggered the above test.
Finally, LLNotificationsUtil::add is made thread-safe by making
LLNotificationChannelBase::mItems thread-safe and defering a call
to LLNotifications::updateItem to the main thread when called
from another thread (using a little statemachine).
Instead of having several AI* classes, it turned out to be easier to
have a namespace: this allows me to define the classes in llcommon but
add (new) 'add' and 'add_modal' functions to 'AIAlert' in llui.
This is needed to avoid a collision with the 'add' functions in
LLNotificationsUtil.
The new add/add_modal makes it a lot easier to just show a caught
alert, prepending or appending new text: it turns out that that is
way more common then a re-throw.
Adjusted code as appropriate.
A system to throw errors that allow for easy error reporting to the user
by showing a translated pop-up alert box with the error message.
The messages use strings.xml for translation and allow the usual
replacement args (ie [FILE] is replaced with a filename).
The exceptions can be cascaded, by adding more (translated) text
when caught and then re-throwing the result.
Macros are being used to support adding a function name prefix
to a message of the current function that the exception is thrown
from.
The syntax is:
<macro>(<line>); to show 'line'
<macro>(<alert>, <line>); to append 'line' to a caught alert.
<macro>(<line>, <alert>); to prepend 'line' to a caught alert.
where <macro> is one of:
THROW_ALERT, THROW_MALERT, THROW_FALERT, THROW_FMALERT,
THROW_ALERTE, THROW_MALERTE, THROW_FALERTE, THROW_FMALERTE, where
M = modal, F = Function name.
and where <line> is one of:
<xmldesc>
<xmldesc>, AIArgs<args>
where <xmldesc> is a string literal that will be looked up
in strings.xml, and <args> is:
(<key>, <replacement>)[<args>]
There are more variations of the macros to throw an arbitrary
class (append _CLASS), include an int code (append C) or
to store the current errno as code (append E).
For example, THROW_MALERTC(code, ...), or THROW_FALERT_CLASS(Foobar, ...),
where the ... is the same as for the macros above.
Documentation and example usage has been added to aialert.h.
* Add LLMD5::clone(unsigned char const*), the inverse of LLMD5::raw_digest.
* Add LLMD5::clone(std::string const&), the inverse of LLMD5::hex_digest.
* Add LLMD5::isFinalized(), returns true if the object is finalized.
* Turn all binary operators into inline friends in the class.
* Fix operator<< to take a LLMD5 const& instead of a LLMD5&.
These changes are needed for / used by AIMultiGrid.
These includes are needed. The current code includes them
in .cpp files *before* including these include files, but
that is not very clean, and not useful.
Actually including what a header file needs makes it more
clear what it drags in, it doesn't drag in more then before.
It also allows to include these headers without having to
includes needed for the included header file in a specific
order, in every .cpp file.
The normal usage is to include the src/ directory of google breakpad
in your application and then include client/ARCH/handler/exception_handler.h
where ARCH is windows, mac or linux.
However, Linden Lab for some reason packaged the breakpad prebuilt
with exception_handler.h installed in ../google_breakpad/exception_handler.h
where "../google_breakpad" is the 'root' of the include tree comparable
with 'src' in the source tree of google breakpad.
Hence, instead of including 'src' one now must include '../include/google_breakpad'
which was already done correctly for non-standable, but not for
standalone (BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR was set to '../include'
with the 'google_breakpad' and is subsequently never used: instead
BREAKPAD_INCLUDE_DIRECTORIES is used (which is set for non-standalone)).
Therefore one much not include "google_breakpad/exception_handler.h",
but just "exception_handler.h" or you rely on somehow the directory
*below* BREAKPAD_INCLUDE_DIRECTORIES to be part of the include path as
well.
Finally LL packages the prebuilt if another duplicate minidump_descriptor.h
in the include root. Also here including "minidump_descriptor.h" would
be better correct, but following the instructions by Google this time
we might as well include the original "client/linux/handler/minidump_descriptor.h".
My repo (http://github.com/AlericInglewood/3p-google-breakpad) doesn't
even put minidump_descriptor.h in the root anymore, only
exception_handler.h. The rest is an exact copy of the 'src' tree with
regard to the headers.
Tested to compile both standalone and non-standalone.