Age | Commit message (Collapse) | Author |
|
The Visual C++ runtime produces typeid(MyClass).name() as "class MyClass".
It's prudent to check for the presence of that prefix before stripping off the
first six characters, but if the first comparison should ever fail, find()
would continue searching the rest of the string for "class " -- a search
guaranteed to fail. Use compare() instead.
|
|
|
|
|
|
A shocking number of LLSingleton subclasses had public constructors -- and in
several instances, were being explicitly instantiated independently of the
LLSingleton machinery. This breaks the new LLSingleton dependency-tracking
machinery. It seems only fair that if you say you want an LLSingleton, there
should only be ONE INSTANCE!
Introduce LLSINGLETON() and LLSINGLETON_EMPTY_CTOR() macros. These handle the
friend class LLSingleton<whatevah>;
and explicitly declare a private nullary constructor.
To try to enforce the LLSINGLETON() convention, introduce a new pure virtual
LLSingleton method you_must_use_LLSINGLETON_macro() which is, as you might
suspect, defined by the macro. If you declare an LLSingleton subclass without
using LLSINGLETON() or LLSINGLETON_EMPTY_CTOR() in the class body, you can't
instantiate the subclass for lack of a you_must_use_LLSINGLETON_macro()
implementation -- which will hopefully remind the coder.
Trawl through ALL LLSingleton subclass definitions, sprinkling in
LLSINGLETON() or LLSINGLETON_EMPTY_CTOR() as appropriate. Remove all explicit
constructor declarations, public or private, along with relevant 'friend class
LLSingleton<myself>' declarations. Where destructors are declared, move them
into private section as well. Where the constructor was inline but nontrivial,
move out of class body.
Fix several LLSingleton abuses revealed by making ctors/dtors private:
LLGlobalEconomy was both an LLSingleton and the base class for
LLRegionEconomy, a non-LLSingleton. (Therefore every LLRegionEconomy instance
contained another instance of the LLGlobalEconomy "singleton.") Extract
LLBaseEconomy; LLGlobalEconomy is now a trivial subclass of that.
LLRegionEconomy, as you might suspect, now derives from LLBaseEconomy.
LLToolGrab, an LLSingleton, was also explicitly instantiated by
LLToolCompGun's constructor. Extract LLToolGrabBase, explicitly instantiated,
with trivial subclass LLToolGrab, the LLSingleton instance.
(WARNING: LLToolGrabBase methods have an unnerving tendency to go after
LLToolGrab::getInstance(). I DO NOT KNOW what should be the relationship
between the instance in LLToolCompGun and the LLToolGrab singleton instance.)
LLGridManager declared a variant constructor accepting (const std::string&),
with the comment:
// initialize with an explicity grid file for testing.
As there is no evidence of this being called from anywhere, delete it.
LLChicletBar's constructor accepted an optional (const LLSD&). As the LLSD
parameter wasn't used, and as there is no evidence of it being passed from
anywhere, delete the parameter.
LLViewerWindow::shutdownViews() was checking LLNavigationBar::
instanceExists(), then deleting its getInstance() pointer -- leaving a
dangling LLSingleton instance pointer, a land mine if any subsequent code
should attempt to reference it. Use deleteSingleton() instead.
~LLAppViewer() was calling LLViewerEventRecorder::instance() and then
explicitly calling ~LLViewerEventRecorder() on that instance -- leaving the
LLSingleton instance pointer pointing to an allocated-but-destroyed instance.
Use deleteSingleton() instead.
|
|
|
|
|
|
Until we reimplement LLCoros on Boost.Fiber, we must hand-implement
coroutine-local data. That presently takes the form of a map keyed on
llcoro::id, whose values are the stacks of currently-initializing LLSingleton
instances.
But since the viewer launches an open-ended number of coroutines, we could end
up with an open-ended number of map entries unless we intentionally prune the
map. So every time we pop the stack to empty, remove that map entry.
This could result in thrashing, a given coroutine's 'initializing' stack being
created and deleted for almost every LLSingleton instantiated by that
coroutine -- but the number of different LLSingletons is necessarily static,
and the lifespan of each is the entire rest of the process. Even a couple
dozen LLSingletons won't thrash that badly.
|
|
The stack we maintain of which LLSingletons are currently initializing only
makes sense when associated with a particular C++ call stack. But each
coroutine introduces another C++ call stack!
Move the initializing stack from function-static storage to
LLSingletonBase::MasterList. Make it a map keyed by llcoro::id. Each coro then
has a stack of its own.
This introduces more dependencies on the MasterList singleton, requiring
additional LLSingleton_manage_master workarounds.
|
|
Until now, the "main coroutine" (the initial context) of each thread left
LLCoros::Current() NULL. The trouble with that is that llcoro::get_id()
returns that CoroData* as an opaque token, and we want distinct values for
every stack in the process. That would not be true if the "main coroutine" on
thread A returned the same value (NULL) as the "main coroutine" on thread B,
and so forth. Give each thread's "main coroutine" a dummy heap CoroData
instance of its own.
|
|
image even if there were no changes
|
|
editing outfit
|
|
We need LLSingleton machinery to be able to reference get_id() without also
depending on all the rest of LLCoros -- since LLCoros isa LLSingleton.
|
|
Change the module-static thread_specific_ptr to a function-static
thread_specific_ptr so it will be initialized on demand -- since LLSingleton
will need to rely on get_id(). Note that since LLCoros isa LLSingleton, we
must take great care to avoid circularity.
Introduce a private helper class LLCoros::Current to obtain and bind that
thread_specific_ptr. Change all existing internal references from the static
thread_specific_ptr to the new Current helper class.
|
|
Specifically, add DEBUG logging to the code that maintains the stack of
LLSingletons currently being initialized. This involves passing
LLSingletonBase's constructor the name of LLSingleton's template parameter
subclass, since during that constructor typeid(*this).name() will only produce
"LLSingletonBase".
Also add logdebugs() and oktolog() helper functions.
|
|
LLError machinery depends on two different LLSingletons. Its is_available()
function is primarily for LLSingleton itself to determine whether it is, or is
not, safe to log. Until both of LLError's LLSingletons have been constructed,
attempting to log LLSingleton operations could produce infinite recursion.
|
|
LLError::abbreviateFile() is specifically to avoid cluttering log output with
the prefix of an absolute file path on the original build system, pointless
for anyone trying to read the log.
|
|
|
|
Raw lllog() doesn't work for varying log level, which is why LL_VLOGS()
exists.
|
|
|
|
In some places we want to log the same information but with different severity
depending on specifics. In other cases we need to test the availability of the
logging subsystem before engaging it. LL_VLOGS() accepts an LLError::ELevel
argument that can differ with each call, while retaining the desirable feature
of deciding only once for each level.
|
|
|
|
|
|
independently of general Snapshot floater
|
|
|
|
near the end of LLAppViewer::cleanup() so every LLSingleton class that hasn't
already been explicitly cleaned up gets a chance to perform its own cleanup.
|
|
|
|
for consistency with everything else, so we can use SUBSYSTEM_CLEANUP() macro
to call it.
|
|
Specifically, log as LLSingleton captures inter-Singleton dependencies. Also
log cleanupAll() calls to cleanupSingleton() and deleteAll() calls to
deleteSingleton(), since they happen in an implicitly-determined order. But do
not log anything during the implicit LLSingletonBase::deleteAll() call
triggered by the runtime destroying the last LLSingleton's static data. That's
too late in the run; even std::cerr might already have been destroyed!
|
|
|
|
Introduce corresponding llcleanup.cpp, llinitdestroyclass.cpp modules to
contain code that performs logging calls.
Track class::method names for LLInitClass<T> and LLDestroyClass<T> subclasses,
and log them when called. The order in which these calls occur could be
relevant to bugs, and could surface the need to convert to LLSingleton
dependencies.
|
|
It used to contain an LLSingleton called Singleton, requiring
LLGlobalEconomy::Singleton::instance() to access it rather than the
conventional LLGlobalEconomy::instance(). This has been fixed, so normalize
references accordingly.
|
|
LLSingleton::getIfExists() has been eliminated. The only remaining way to
detect whether a given LLSingleton has been instantiated is to call
instanceExists(). But the relevant cleanup code should be refactored to
cleanupSingleton() anyway, which would make this specific call moot.
|
|
This fixes fatal warnings.
|
|
clang gets nervous about expressions that call functions inside typeid(), even
though these particular typeid() calls are runtime expressions on runtime
values. Extract the offending calls to a previous statement.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Previous code would crump with LL_ERRS. But a bad image file should fail only
the image load -- not crash the viewer.
While at it, validate all components present, not just 0, 1, 2.
While at it, make the failure message report which component and what the
mismatched dimensions are, not just "Components don't have matching
dimensions!"
|
|
Specifically, manually apply changesets b4db8a8 and b98371d from
nat_linden/viewer-mac-mainloop. We need to throw from a new place, but if we
threw const char* (current convention), the new throw wouldn't be patched when
we merge to new exception convention.
|
|
These comments are inherently fragile, in that they enumerate all present
callers of certain methods. Adding, removing or relocating calls would
invalidate these comments. However, the LLImageJ2CKDU implementation is
probably pretty stable by now.
|
|
|
|
|