Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VS 2013 thought we were storing an initialization-list.
|
|
An exception in the LLSingleton subclass constructor, or in its
initSingleton() method, could leave the LLSingleton machinery in a bad state:
the failing instance would remain in the MasterList, also on the stack of
initializing LLSingletons. Catch exceptions in either and perform relevant
cleanup.
This problem is highlighted by test programs, in which LL_ERRS throws an
exception rather than crashing the whole process.
In the relevant catch clauses, clean up the initializing stack BEFORE logging.
Otherwise we get tangled up recording bogus dependencies.
Move capture_dependency() out of finishInitializing(): it must be called by
every valid getInstance() call, both from LLSingleton and LLParamSingleton.
Introduce new CONSTRUCTED EInitState value to distinguish "have called the
constructor but not yet the initSingleton() method" from "currently within
initSingleton() method." This is transient, but we execute the 'switch' on
state within that moment. One could argue that the previous enum used
INITIALIZING for current CONSTRUCTED, and INITIALIZED meant INITIALIZING too,
but this is clearer.
Introduce template LLSingletonBase::classname() helper methods to clarify
verbose demangle(typeid(stuff).name()) calls.
Similarly, introduce LLSingleton::pop_initializing() shorthand method.
|
|
Add try/catch clauses to constructSingleton() (to catch exceptions in the
subclass constructor) and finishInitializing() (to catch exceptions in the
subclass initSingleton() method). Each of these catch clauses rethrows the
exception -- they're for cleanup, not for ultimate handling.
Introduce LLSingletonBase::reset_initializing(list_t::size_t). The idea is
that since we can't know whether the exception happened before or after the
push_initializing() call in LLSingletonBase's constructor, we can't just pop
the stack. Instead, constructSingleton() captures the stack size before
attempting to construct the new LLSingleton subclass. On exception, it calls
reset_initializing() to restore the stack to that size.
Naturally that requires a corresponding LLSingleton_manage_master method,
whose MasterList specialization is a no-op.
finishInitializing()'s exception handling is a bit simpler because it has a
constructed LLSingleton subclass instance in hand, therefore
push_initializing() has definitely been called, therefore it can call
pop_initializing().
Break out new static capture_dependency() method from finishInitializing()
because, in the previous LLSingleton::getInstance() implementation, the logic
now wrapped in capture_dependency() was reached even in the INITIALIZED case.
TODO: Add a new EInitState to differentiate "have been constructed, now
calling initSingleton()" from "fully initialized, normal case" -- in the
latter control path we should not be calling capture_dependency().
The LLSingleton_manage_master<LLSingletonBase::MasterList> specialization's
get_initializing() function (which called get_initializing_from()) was
potentially dangerous. get_initializing() is called by push_initializing(),
which (in the general case) is called by LLSingletonBase's constructor. If
somehow the MasterList's LLSingletonBase constructor ended up calling
get_initializing(), it would have called get_initializing_from(), passing an
LLSingletonBase which had not yet been constructed into the MasterList. In
particular, its mInitializing map would not yet have been initialized at all.
Since the MasterList must not, by design, depend on any other LLSingletons,
LLSingleton_manage_master<LLSingletonBase::MasterList>::get_initializing()
need not return a list from the official mInitializing map anyway. It can, and
should, and now does, return a static dummy list. That obviates
get_initializing_from(), which is removed.
That in turn means we no longer need to pass get_initializing() an
LLSingletonBase*. Remove that parameter.
|
|
LLParamSingleton contained a static member mutex. Unfortunately that wasn't
guaranteed to be initialized by the time its getInstance() was entered. Use a
function-local static instead.
|
|
|
|
from LLParamSingleton::initSingleton().
|
|
|
|
This was forbidden, but AndreyK points out cases in which LLParamSingleton::
initSingleton() should in fact be allowed to circle back to its own instance()
method. Use a recursive_mutex instead of plain mutex to permit that; remove
LL_ERRS preventing it.
Add LLParamSingleton::instance() method that calls
LLParamSingleton::getInstance(). Inheriting LLSingleton::instance() called
LLSingleton::getInstance() -- not at all what we want.
Add LLParamSingleton unit tests.
|
|
|
|
|
|
Simplify LLSingleton::SingletonLifetimeManager to SingletonInitializer: that
struct has not been responsible for deletion ever since LLSingletonBase
acquired dependency-ordered deleteAll().
Move SingletonData::mInitState changes from SingletonLifetimeManager to
constructSingleton() method. Similarly, constructSingleton() now sets
SingletonData::mInstance instead of making its caller store the pointer.
Add variadic arguments to LLSingleton::constructSingleton() so we can reuse it
for LLParamSingleton.
Add finishInitializing() method to encapsulate logic reused for
getInstance()'s INITIALIZING and DELETED cases.
Make LLParamSingleton a subclass of LLSingleton, just as LLLockedSingleton is
a subclass of LLParamSingleton. Make LLParamSingleton a friend of LLSingleton,
so it can access private members of LLSingleton without also granting access
to any DERIVED_CLASS subclass. This eliminates the need for protected
getInitState().
LLParamSingleton::initParamSingleton() reuses LLSingleton::constructSingleton()
and finishInitializing(). Its getInstance() method completely replaces
LLSingleton::getInstance(): in most EInitStates, LLParamSingleton::getInstance()
is an error.
Use a std::mutex to serialize calls to LLParamSingleton::initParamSingleton()
and getInstance(). While LLSingleton::getInstance() relies on the "initialized
exactly once" guarantee for block-scope static declarations, LLParamSingleton
cannot rely on the same mechanism.
LLLockedSingleton is now a very succinct subclass of LLParamSingleton -- they
have very similar functionality.
Giving the LLSINGLETON() macro variadic arguments eliminates the need for a
separate LLPARAMSINGLETON() macro, while continuing to support existing usage.
|
|
|
|
Use them in place of awkward try/catch test boilerplate.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mail drop does not have any outstanding events.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
instead of a variable of type decltype(expression).
Using SHGetKnownFolderPath(FOLDERID_Fonts) in LLFontGL::getFontPathSystem()
requires new Windows #include files.
A variable with a constructor can't be declared within the braces of a switch
statement, even outside any of its case clauses.
|
|
|
|
Use LLStringUtil::getenv() or getoptenv() whenever we fetch a string that will
be used as a pathname.
Use LLFile::tmpdir() instead of getenv("TEMP").
As an added extra-special bonus, finally clean up $TMP/llcontrol-test-zzzzzz
directories that have been accumulating every time we run a local build!
|
|
Move Windows-flavored llstring_getoptenv() to Windows-specific section of
llstring.cpp.
boost::optional type must be stated explicitly to initialize with a value.
On platforms where llwchar is the same as wchar_t, LLWString is the same as
std::wstring, so ll_convert specializations for std::wstring would duplicate
those for LLWString. Defend against that.
The compilers we use don't like 'return condition? { expr } : {}', in which we
hope to construct and return an instance of the declared return type without
having to restate the type. It works to use an explicit 'if' statement.
|
|
Add ll_convert<TO, FROM> template, used as (e.g.):
ll_convert<std::string>(value_of_some_other_string_type);
There is no generic template implementation -- the template exists solely to
provide generic aliases for a bewildering family of llstring.h string-
conversion functions with highly-specific names. There's a generic
implementation, though, for the degenerate case where FROM and TO are
identical.
Add ll_convert<> specialization aliases for most of the string-conversion
functions declared in llstring.h, including the Windows-specific ones
involving llutf16string and std::wstring.
Add a mini-lecture in llstring.h about appropriate use of string types on
Windows.
Add LL_WCHAR_T_NATIVE llpreprocessor.h macro so we can detect whether to
provide separate conversions for llutf16string and std::wstring, or whether
those would collide because the types are identical.
Add inline ll_convert_wide_to_string(const std::wstring&) overloads so caller
isn't required to call arg.c_str(), which naturally permits an ll_convert
alias.
Add ll_convert_wide_to_wstring(), ll_convert_wstring_to_wide() as placeholders
for converting between Windows std::wstring and Linden LLWString, with
corresponding ll_convert aliases. We don't yet have library code to perform
such conversions officially; for now, just copy characters.
Add LLStringUtil::getenv(key) and getoptenv(key) functions. The latter returns
boost::optional<string_type> in case the caller needs to detect absence of a
given environment variable rather than simply accepting a default value.
Naturally getenv(), which accepts a default, is implemented using getoptenv().
getoptenv(), in turn, is implemented using an underlying llstring_getoptenv().
On Windows, llstring_getoptenv() returns boost::optional<std::wstring> (based
on GetEnvironmentVariableW()), whereas elsewhere, llstring_getoptenv() returns
boost::optional<std::string> (based on classic Posix getenv()).
The beauty of generic ll_convert is that the portable LLStringUtilBase<T>::
getoptenv() template can call the platform-specific llstring_getoptenv() and
transparently perform whatever conversion is necessary to return the desired
string_type.
Add windows_message<T>(error) template, with an overload that implicitly calls
GetLastError(). We provide a single concrete windows_message<std::wstring>()
implementation because that's what we get from Windows FormatMessageW() --
everything else is a generic conversion to the desired target string type.
This obviates llprocess.cpp's previous WindowsErrorString() implementation --
reimplement using windows_message<std::string>().
|
|
Instead of returning a wchar_t* and requiring the caller to delete it later,
return a std::basic_string<wchar_t> that's self-cleaning. If the caller wants
a wchar_t*, s/he can call c_str() on the returned string.
Default the code_page parameter to CP_UTF8, since we try to be really
consistent about using UTF-8 encoding for all our internal std::strings.
|
|
|
|
|