Commit 91fa31c0 authored by AndreyL ProductEngine's avatar AndreyL ProductEngine

Downstream merge from lindenlab/viewer-serval

parents 2d69438e f13cc44f
......@@ -555,3 +555,4 @@ ab2ec5c5423b277d23fd0511ce50c15123ff2e03 6.2.3-release
ece699718f163921717bb95a6131e94af4c4138f 6.3.1-release
07f5d5bc9faebb45695853d40a9549773db816c0 6.3.2-release
d9a4bd15e2c852953d6c8e84d6f3b7ca442c0e7f 6.3.3-release
4033b3f57e76f087235145a3016886ccdc87ffa3 6.3.4-release
......@@ -29,18 +29,6 @@
#include "llinventorytype.h"
#include "llinventorydefines.h"
static LLTranslationBridge* sTrans = NULL;
// static
void LLWearableType::initClass(LLTranslationBridge* trans)
{
sTrans = trans;
}
void LLWearableType::cleanupClass()
{
delete sTrans;
}
struct WearableEntry : public LLDictionaryEntry
{
......@@ -53,7 +41,7 @@ struct WearableEntry : public LLDictionaryEntry
LLDictionaryEntry(name),
mAssetType(assetType),
mDefaultNewName(default_new_name),
mLabel(sTrans->getString(name)),
mLabel(LLWearableType::getInstance()->mTrans->getString(name)),
mIconName(iconName),
mDisableCameraSwitch(disable_camera_switch),
mAllowMultiwear(allow_multiwear)
......@@ -68,7 +56,7 @@ struct WearableEntry : public LLDictionaryEntry
BOOL mAllowMultiwear;
};
class LLWearableDictionary : public LLSingleton<LLWearableDictionary>,
class LLWearableDictionary : public LLParamSingleton<LLWearableDictionary>,
public LLDictionary<LLWearableType::EType, WearableEntry>
{
LLSINGLETON(LLWearableDictionary);
......@@ -99,6 +87,27 @@ LLWearableDictionary::LLWearableDictionary()
addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
}
// class LLWearableType
LLWearableType::LLWearableType(LLTranslationBridge* trans)
{
mTrans = trans;
}
LLWearableType::~LLWearableType()
{
delete mTrans;
}
void LLWearableType::initSingleton()
{
// To make sure all wrapping functions will crash without initing LLWearableType;
LLWearableDictionary::initParamSingleton();
// Todo: consider merging LLWearableType and LLWearableDictionary
}
// static
LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name)
{
......
......@@ -42,8 +42,12 @@ class LLTranslationBridge
};
class LLWearableType
class LLWearableType : public LLParamSingleton<LLWearableType>
{
LLSINGLETON(LLWearableType, LLTranslationBridge* trans);
~LLWearableType();
friend struct WearableEntry;
void initSingleton();
public:
enum EType
{
......@@ -70,9 +74,8 @@ class LLWearableType
WT_NONE = -1,
};
static void initClass(LLTranslationBridge* trans); // initializes static members
static void cleanupClass(); // initializes static members
// Most methods are wrappers for dictionary, but if LLWearableType is not initialized,
// they will crash. Whole LLWearableType is just wrapper for convinient calls.
static const std::string& getTypeName(EType type);
static const std::string& getTypeDefaultNewName(EType type);
static const std::string& getTypeLabel(EType type);
......@@ -81,11 +84,12 @@ class LLWearableType
static LLInventoryType::EIconName getIconName(EType type);
static BOOL getDisableCameraSwitch(EType type);
static BOOL getAllowMultiwear(EType type);
static EType inventoryFlagsToWearableType(U32 flags);
static EType inventoryFlagsToWearableType(U32 flags);
protected:
LLWearableType() {}
~LLWearableType() {}
LLTranslationBridge* mTrans;
};
#endif // LL_LLWEARABLETYPE_H
......@@ -134,12 +134,6 @@ LLSingletonBase::list_t& LLSingletonBase::get_initializing()
return LLSingletonBase::MasterList::instance().get_initializing_();
}
//static
LLSingletonBase::list_t& LLSingletonBase::get_initializing_from(MasterList* master)
{
return master->get_initializing_();
}
LLSingletonBase::~LLSingletonBase() {}
void LLSingletonBase::push_initializing(const char* name)
......@@ -156,7 +150,7 @@ void LLSingletonBase::pop_initializing()
if (list.empty())
{
logerrs("Underflow in stack of currently-initializing LLSingletons at ",
demangle(typeid(*this).name()).c_str(), "::getInstance()");
classname(this).c_str(), "::getInstance()");
}
// Now we know list.back() exists: capture it
......@@ -178,14 +172,39 @@ void LLSingletonBase::pop_initializing()
if (back != this)
{
logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ",
demangle(typeid(*this).name()).c_str(), "::getInstance() trying to pop ",
demangle(typeid(*back).name()).c_str());
classname(this).c_str(), "::getInstance() trying to pop ",
classname(back).c_str());
}
// log AFTER popping so logging singletons don't cry circularity
log_initializing("Popping", typeid(*back).name());
}
void LLSingletonBase::reset_initializing(list_t::size_type size)
{
// called for cleanup in case the LLSingleton subclass constructor throws
// an exception
// The tricky thing about this, the reason we have a separate method
// instead of just calling pop_initializing(), is (hopefully remote)
// possibility that the exception happened *before* the
// push_initializing() call in LLSingletonBase's constructor. So only
// remove the stack top if in fact we've pushed something more than the
// previous size.
list_t& list(get_initializing());
while (list.size() > size)
{
list.pop_back();
}
// as in pop_initializing()
if (list.empty())
{
MasterList::instance().cleanup_initializing_();
}
}
//static
void LLSingletonBase::log_initializing(const char* verb, const char* name)
{
......@@ -197,7 +216,7 @@ void LLSingletonBase::log_initializing(const char* verb, const char* name)
ri != rend; ++ri)
{
LLSingletonBase* sb(*ri);
LL_CONT << ' ' << demangle(typeid(*sb).name());
LL_CONT << ' ' << classname(sb);
}
LL_ENDL;
}
......@@ -231,7 +250,7 @@ void LLSingletonBase::capture_dependency(list_t& initializing, EInitState initSt
// 'found' is an iterator; *found is an LLSingletonBase*; **found
// is the actual LLSingletonBase instance.
LLSingletonBase* foundp(*found);
out << demangle(typeid(*foundp).name()) << " -> ";
out << classname(foundp) << " -> ";
}
// We promise to capture dependencies from both the constructor
// and the initSingleton() method, so an LLSingleton's instance
......@@ -245,7 +264,7 @@ void LLSingletonBase::capture_dependency(list_t& initializing, EInitState initSt
if (initState == CONSTRUCTING)
{
logerrs("LLSingleton circularity in Constructor: ", out.str().c_str(),
demangle(typeid(*this).name()).c_str(), "");
classname(this).c_str(), "");
}
else if (it_next == initializing.end())
{
......@@ -256,14 +275,14 @@ void LLSingletonBase::capture_dependency(list_t& initializing, EInitState initSt
// Example: LLNotifications singleton initializes default channels.
// Channels register themselves with singleton once done.
logdebugs("LLSingleton circularity: ", out.str().c_str(),
demangle(typeid(*this).name()).c_str(), "");
classname(this).c_str(), "");
}
else
{
// Actual circularity with other singleton (or single singleton is used extensively).
// Dependency can be unclear.
logwarns("LLSingleton circularity: ", out.str().c_str(),
demangle(typeid(*this).name()).c_str(), "");
classname(this).c_str(), "");
}
}
else
......@@ -276,8 +295,8 @@ void LLSingletonBase::capture_dependency(list_t& initializing, EInitState initSt
if (current->mDepends.insert(this).second)
{
// only log the FIRST time we hit this dependency!
logdebugs(demangle(typeid(*current).name()).c_str(),
" depends on ", demangle(typeid(*this).name()).c_str());
logdebugs(classname(current).c_str(),
" depends on ", classname(this).c_str());
}
}
}
......@@ -336,19 +355,19 @@ void LLSingletonBase::cleanupAll()
sp->mCleaned = true;
logdebugs("calling ",
demangle(typeid(*sp).name()).c_str(), "::cleanupSingleton()");
classname(sp).c_str(), "::cleanupSingleton()");
try
{
sp->cleanupSingleton();
}
catch (const std::exception& e)
{
logwarns("Exception in ", demangle(typeid(*sp).name()).c_str(),
logwarns("Exception in ", classname(sp).c_str(),
"::cleanupSingleton(): ", e.what());
}
catch (...)
{
logwarns("Unknown exception in ", demangle(typeid(*sp).name()).c_str(),
logwarns("Unknown exception in ", classname(sp).c_str(),
"::cleanupSingleton()");
}
}
......@@ -363,7 +382,7 @@ void LLSingletonBase::deleteAll()
{
// Capture the class name first: in case of exception, don't count on
// being able to extract it later.
const std::string name = demangle(typeid(*sp).name());
const std::string name = classname(sp);
try
{
// Call static method through instance function pointer.
......@@ -440,7 +459,17 @@ void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, co
log(LLError::LEVEL_ERROR, p1, p2, p3, p4);
// The other important side effect of LL_ERRS() is
// https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
LLError::crashAndLoop(std::string());
std::ostringstream out;
out << p1 << p2 << p3 << p4;
auto crash = LLError::getFatalFunction();
if (crash)
{
crash(out.str());
}
else
{
LLError::crashAndLoop(out.str());
}
}
std::string LLSingletonBase::demangle(const char* mangled)
......
This diff is collapsed.
......@@ -506,16 +506,10 @@ namespace tut
replyName = waiter.getName0();
errorName = waiter.getName1();
WrapLLErrs capture;
try
{
result = waiter.suspendWithLog();
debug("no exception");
}
catch (const WrapLLErrs::FatalException& e)
{
debug(STRINGIZE("exception " << e.what()));
threw = e.what();
}
threw = capture.catch_llerrs([&waiter, &debug](){
result = waiter.suspendWithLog();
debug("no exception");
});
}
END
}
......@@ -762,18 +756,13 @@ namespace tut
{
LLCoroEventPumps waiter;
WrapLLErrs capture;
try
{
result = waiter.postAndSuspendWithLog(
LLSDMap("value", 31)("fail", LLSD()),
immediateAPI.getPump(), "reply", "error");
debug("no exception");
}
catch (const WrapLLErrs::FatalException& e)
{
debug(STRINGIZE("exception " << e.what()));
threw = e.what();
}
threw = capture.catch_llerrs(
[&waiter, &debug](){
result = waiter.postAndSuspendWithLog(
LLSDMap("value", 31)("fail", LLSD()),
immediateAPI.getPump(), "reply", "error");
debug("no exception");
});
}
END
}
......
......@@ -22,6 +22,7 @@
#include "llsdutil.h"
#include "stringize.h"
#include "tests/wrapllerrs.h"
#include "../test/catch_and_store_what_in.h"
#include <map>
#include <string>
......@@ -630,16 +631,9 @@ namespace tut
void call_exc(const std::string& func, const LLSD& args, const std::string& exc_frag)
{
std::string threw;
try
{
work(func, args);
}
catch (const std::runtime_error& e)
{
cout << "*** " << e.what() << '\n';
threw = e.what();
}
std::string threw = catch_what<std::runtime_error>([this, &func, &args](){
work(func, args);
});
ensure_has(threw, exc_frag);
}
......@@ -717,15 +711,9 @@ namespace tut
LLSD attempts(LLSDArray(17)(LLSDMap("pi", 3.14)("two", 2)));
foreach(LLSD ae, inArray(attempts))
{
std::string threw;
try
{
work.add("freena_err", "freena", freena, ae);
}
catch (const std::exception& e)
{
threw = e.what();
}
std::string threw = catch_what<std::exception>([this, &ae](){
work.add("freena_err", "freena", freena, ae);
});
ensure_has(threw, "must be an array");
}
}
......@@ -734,15 +722,9 @@ namespace tut
void object::test<2>()
{
set_test_name("map-style registration with badly-formed defaults");
std::string threw;
try
{
work.add("freena_err", "freena", freena, LLSDArray("a")("b"), 17);
}
catch (const std::exception& e)
{
threw = e.what();
}
std::string threw = catch_what<std::exception>([this](){
work.add("freena_err", "freena", freena, LLSDArray("a")("b"), 17);
});
ensure_has(threw, "must be a map or an array");
}
......@@ -750,17 +732,11 @@ namespace tut
void object::test<3>()
{
set_test_name("map-style registration with too many array defaults");
std::string threw;
try
{
work.add("freena_err", "freena", freena,
LLSDArray("a")("b"),
LLSDArray(17)(0.9)("gack"));
}
catch (const std::exception& e)
{
threw = e.what();
}
std::string threw = catch_what<std::exception>([this](){
work.add("freena_err", "freena", freena,
LLSDArray("a")("b"),
LLSDArray(17)(0.9)("gack"));
});
ensure_has(threw, "shorter than");
}
......@@ -768,17 +744,11 @@ namespace tut
void object::test<4>()
{
set_test_name("map-style registration with too many map defaults");
std::string threw;
try
{
work.add("freena_err", "freena", freena,
LLSDArray("a")("b"),
LLSDMap("b", 17)("foo", 3.14)("bar", "sinister"));
}
catch (const std::exception& e)
{
threw = e.what();
}
std::string threw = catch_what<std::exception>([this](){
work.add("freena_err", "freena", freena,
LLSDArray("a")("b"),
LLSDMap("b", 17)("foo", 3.14)("bar", "sinister"));
});
ensure_has(threw, "nonexistent params");
ensure_has(threw, "foo");
ensure_has(threw, "bar");
......@@ -1039,16 +1009,9 @@ namespace tut
// We don't have a comparable helper function for the one-arg
// operator() method, and it's not worth building one just for this
// case. Write it out.
std::string threw;
try
{
work(LLSDMap("op", "freek"));
}
catch (const std::runtime_error& e)
{
cout << "*** " << e.what() << "\n";
threw = e.what();
}
std::string threw = catch_what<std::runtime_error>([this](){
work(LLSDMap("op", "freek"));
});
ensure_has(threw, "bad");
ensure_has(threw, "op");
ensure_has(threw, "freek");
......
......@@ -350,15 +350,9 @@ namespace tut
// Now let the timer expire.
filter.forceTimeout();
// Notice the timeout.
std::string threw;
try
{
mainloop.post(17);
}
catch (const WrapLLErrs::FatalException& e)
{
threw = e.what();
}
std::string threw = capture.catch_llerrs([this](){
mainloop.post(17);
});
ensure_contains("errorAfter() timeout exception", threw, "timeout");
// Timing out cancels the timer. Verify that.
listener0.reset(0);
......
......@@ -198,14 +198,9 @@ namespace tut
{
WrapLLErrs wrapper;
Keyed::instance_iter i(Keyed::beginInstances());
try
{
delete keyed;
}
catch (const WrapLLErrs::FatalException& e)
{
what = e.what();
}
what = wrapper.catch_llerrs([&keyed](){
delete keyed;
});
}
ensure(! what.empty());
}
......@@ -219,14 +214,9 @@ namespace tut
{
WrapLLErrs wrapper;
Keyed::key_iter i(Keyed::beginKeys());
try
{
delete keyed;
}
catch (const WrapLLErrs::FatalException& e)
{
what = e.what();
}
what = wrapper.catch_llerrs([&keyed](){
delete keyed;
});
}
ensure(! what.empty());
}
......@@ -240,14 +230,9 @@ namespace tut
{
WrapLLErrs wrapper;
Unkeyed::instance_iter i(Unkeyed::beginInstances());
try
{
delete unkeyed;
}
catch (const WrapLLErrs::FatalException& e)
{
what = e.what();
}
what = wrapper.catch_llerrs([&unkeyed](){
delete unkeyed;
});
}
ensure(! what.empty());
}
......