DRTVWR-564: WIP: add LLEventPumps::registerPumpFactory()
and registerTypeFactory(). Untested. This will support registering just-in-time LLEventAPI instances, instantiated on demand.master
parent
cdbd06e8ed
commit
a4ff9caf69
|
|
@ -68,19 +68,51 @@
|
|||
LLEventPumps::LLEventPumps():
|
||||
mFactories
|
||||
{
|
||||
{ "LLEventStream", [](const std::string& name, bool tweak)
|
||||
{ "LLEventStream", [](const std::string& name, bool tweak, const std::string& /*type*/)
|
||||
{ return new LLEventStream(name, tweak); } },
|
||||
{ "LLEventMailDrop", [](const std::string& name, bool tweak)
|
||||
{ "LLEventMailDrop", [](const std::string& name, bool tweak, const std::string& /*type*/)
|
||||
{ return new LLEventMailDrop(name, tweak); } }
|
||||
},
|
||||
mTypes
|
||||
{
|
||||
// LLEventStream is the default for obtain(), so even if somebody DOES
|
||||
// call obtain("placeholder"), this sample entry won't break anything.
|
||||
{ "placeholder", "LLEventStream" }
|
||||
// { "placeholder", "LLEventStream" }
|
||||
}
|
||||
{}
|
||||
|
||||
bool LLEventPumps::registerTypeFactory(const std::string& type, const TypeFactory& factory)
|
||||
{
|
||||
auto found = mFactories.find(type);
|
||||
// can't re-register a TypeFactory for a type name that's already registered
|
||||
if (found != mFactories.end())
|
||||
return false;
|
||||
// doesn't already exist, go ahead and register
|
||||
mFactories[type] = factory;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLEventPumps::registerPumpFactory(const std::string& name, const PumpFactory& factory)
|
||||
{
|
||||
// Do we already have a pump by this name?
|
||||
if (mPumpMap.find(name) != mPumpMap.end())
|
||||
return false;
|
||||
// Do we already have an override for this pump name?
|
||||
if (mTypes.find(name) != mTypes.end())
|
||||
return false;
|
||||
// Leverage the two-level lookup implemented by mTypes (pump name -> type
|
||||
// name) and mFactories (type name -> factory). We could instead create a
|
||||
// whole separate (pump name -> factory) map, and look in both; or we
|
||||
// could change mTypes to (pump name -> factory) and, for typical type-
|
||||
// based lookups, use a "factory" that looks up the real factory in
|
||||
// mFactories. But this works, and we don't expect many calls to make() -
|
||||
// either explicit or implicit via obtain().
|
||||
// Create a bogus type name extremely unlikely to collide with an actual type.
|
||||
static std::string nul(1, '\0');
|
||||
std::string type_name{ nul + name };
|
||||
mTypes[name] = type_name;
|
||||
mFactories[type_name] = factory;
|
||||
return true;
|
||||
}
|
||||
|
||||
LLEventPump& LLEventPumps::obtain(const std::string& name)
|
||||
{
|
||||
PumpMap::iterator found = mPumpMap.find(name);
|
||||
|
|
@ -114,7 +146,7 @@ LLEventPump& LLEventPumps::make(const std::string& name, bool tweak,
|
|||
// Passing an unrecognized type name is a no-no
|
||||
LLTHROW(BadType(type));
|
||||
}
|
||||
auto newInstance = (found->second)(name, tweak);
|
||||
auto newInstance = (found->second)(name, tweak, type);
|
||||
// LLEventPump's constructor implicitly registers each new instance in
|
||||
// mPumpMap. But remember that we instantiated it (in mOurPumps) so we'll
|
||||
// delete it later.
|
||||
|
|
|
|||
|
|
@ -268,6 +268,43 @@ public:
|
|||
LLEventPump& make(const std::string& name, bool tweak=false,
|
||||
const std::string& type=std::string());
|
||||
|
||||
/// function passed to registerTypeFactory()
|
||||
typedef std::function<LLEventPump*(const std::string& name, bool tweak, const std::string& type)> TypeFactory;
|
||||
|
||||
/**
|
||||
* Register a TypeFactory for use with make(). When make() is called with
|
||||
* the specified @a type string, call @a factory(name, tweak, type) to
|
||||
* instantiate it.
|
||||
*
|
||||
* Returns true if successfully registered, false if there already exists
|
||||
* a TypeFactory for the specified @a type name.
|
||||
*/
|
||||
bool registerTypeFactory(const std::string& type, const TypeFactory& factory);
|
||||
|
||||
/// function passed to registerPumpFactory()
|
||||
typedef std::function<LLEventPump*(const std::string&)> PumpFactory;
|
||||
|
||||
/**
|
||||
* Register a PumpFactory for use with obtain(). When obtain() is called
|
||||
* with the specified @a name string, if an LLEventPump with the specified
|
||||
* @a name doesn't already exist, call @a factory(name) to instantiate it.
|
||||
*
|
||||
* Returns true if successfully registered, false if there already exists
|
||||
* a factory override for the specified @a name.
|
||||
*
|
||||
* PumpFactory does not support @a tweak because it's only called when
|
||||
* <i>that particular</i> @a name is passed to obtain(). Bear in mind that
|
||||
* <tt>obtain(name)</tt> might still bypass the caller's PumpFactory for a
|
||||
* couple different reasons:
|
||||
*
|
||||
* * registerPumpFactory() returns false because there's already a factory
|
||||
* override for the specified @name
|
||||
* * between a successful <tt>registerPumpFactory(name)</tt> call (returns
|
||||
* true) and a call to <tt>obtain(name)</tt>, someone explicitly
|
||||
* instantiated an LLEventPump(name), so obtain(name) returned that.
|
||||
*/
|
||||
bool registerPumpFactory(const std::string& name, const PumpFactory& factory);
|
||||
|
||||
/**
|
||||
* Find the named LLEventPump instance. If it exists post the message to it.
|
||||
* If the pump does not exist, do nothing.
|
||||
|
|
@ -325,7 +362,7 @@ testable:
|
|||
typedef std::set<LLEventPump*> PumpSet;
|
||||
PumpSet mOurPumps;
|
||||
// for make(), map string type name to LLEventPump subclass factory function
|
||||
typedef std::map<std::string, std::function<LLEventPump*(const std::string&, bool)>> PumpFactories;
|
||||
typedef std::map<std::string, PumpFactory> PumpFactories;
|
||||
// Data used by make().
|
||||
// One might think mFactories and mTypes could reasonably be static. So
|
||||
// they could -- if not for the fact that make() or obtain() might be
|
||||
|
|
|
|||
Loading…
Reference in New Issue