LDMX Software
|
Factory to dynamically create objects derived from a specific prototype class. More...
#include <Factory.h>
Public Types | |
using | PrototypeMaker = PrototypePtr(*)(PrototypeConstructorArgs...) |
the signature of a function that can be used by this factory to dynamically create a new object. | |
Public Member Functions | |
template<typename DerivedType > | |
uint64_t | declare () |
register a new object to be constructible | |
PrototypePtr | make (const std::string &full_name, PrototypeConstructorArgs... maker_args) |
make a new object by name | |
template<class UnaryFunction > | |
void | apply (UnaryFunction f) const |
Apply the input UnaryFunction to each entry in the inventory. | |
Factory (Factory const &)=delete | |
delete the copy constructor | |
void | operator= (Factory const &)=delete |
delete the assignment operator | |
Static Public Member Functions | |
static Factory & | get () |
get the factory instance | |
Private Member Functions | |
Factory ()=default | |
private constructor to prevent creation | |
Static Private Member Functions | |
template<typename DerivedType > | |
static PrototypePtr | maker (PrototypeConstructorArgs... args) |
make a new DerivedType returning a PrototypePtr | |
Private Attributes | |
std::unordered_map< std::string, PrototypeMaker > | library_ |
library of possible objects to create | |
std::vector< PrototypePtr > | warehouse_ |
warehouse of objects that have already been created | |
Factory to dynamically create objects derived from a specific prototype class.
This factory is a singleton class meaning it cannot be created by the user.
Prototype | the type of object that this factory creates. This should be the base class that all types in this factory derive from. |
PrototypePtr | the type of pointer that the factory creates |
PrototypeConstructorArgs | parameter pack of arguments to pass to the object constructor. |
The factory itself works in two steps.
Using an unnamed namespace defines the variables inside it as having internal linkage and as implicitly static. Having internal linkage allows us to have repeat variable names across different source files. Being static means that the variable is guaranteed to be constructed during library load time.
This if we put the following code in the source file for a class deriving from our prototype, it will be declared to the factory during library load.
The details of how this is handled is documented in Storage Class Specifiers.
Using the factory effecitvely can be done in situations where many classes all follow the same design structure, but have different implementations for specific steps. In order to reflect this "same design structure", we define an abstract base class for all of our derived classes from which to inherit. This abstract base class is our "prototype".
Below is a rudimentary example that shows you the basics of this class.
This LibraryEntry
prototype class satisfies our requirements. It also defines a helpful "declaration" macro for derived classes to use.
Here are a few example derived classes.
Since the DECLARE_LIBRARYENTRY
macro defines a function that is decorated with a compiler attribute causing the function to be called at library-load time, the registration of our various library entries is automatically done before the execution of main
(or after if the loadLibrary function is used). For simplicity, let's compile these sources files together with a main defined below.
Compiling these files together into the fave-things
executable would then lead to the following behavior.
using simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::PrototypeMaker = PrototypePtr (*)(PrototypeConstructorArgs...) |
|
inline |
Apply the input UnaryFunction to each entry in the inventory.
UnaryFunction is simply passed dirctly to std::for_each so look there for requirements upon it.
Definition at line 283 of file Factory.h.
References simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::warehouse_.
Referenced by simcore::Simulator::beforeNewRun(), simcore::ReSimulator::produce(), simcore::Simulator::produce(), and simcore::RunManager::setupPhysics().
|
inline |
register a new object to be constructible
We insert the new object into the library after checking that it hasn't been defined before.
DerivedType | object type to declare |
Definition at line 241 of file Factory.h.
References simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::library_.
|
inlinestatic |
get the factory instance
Using a static function variable gaurantees that the factory is created as soon as it is needed and that it is deleted before the program completes.
Definition at line 217 of file Factory.h.
Referenced by simcore::Simulator::beforeNewRun(), simcore::GammaPhysics::ConstructProcess(), simcore::RunManager::Initialize(), simcore::ReSimulator::produce(), simcore::Simulator::produce(), and simcore::RunManager::setupPhysics().
|
inline |
make a new object by name
We look through the library to find the requested object. If found, we create one and return a pointer to the newly created object. If not found, we raise an exception.
Exception | if the input object name could not be found |
The arguments to the maker are determined at compiletime using the template parameters of Factory.
[in] | full_name | name of class to create, same name as passed to declare |
[in] | maker_args | parameter pack of arguments to pass on to maker |
Definition at line 265 of file Factory.h.
References simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::library_, and simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::warehouse_.
Referenced by simcore::GammaPhysics::ConstructProcess(), simcore::RunManager::Initialize(), and simcore::RunManager::setupPhysics().
|
inlinestaticprivate |
make a new DerivedType returning a PrototypePtr
Basically a copy of what std::make_unique
or std::make_shared
do but with the following changes:
This is where we required that PrototypePtr has the same behavior as STL smart pointers. The PrototypePtr class must be able to be constructed from a pointer to a derived class and must take ownership of the new object.
DerivedType | type of derived object we should create |
[in] | args | constructor arguments for derived type construction |
Definition at line 314 of file Factory.h.
|
private |
library of possible objects to create
Definition at line 323 of file Factory.h.
Referenced by simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::declare(), and simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::make().
|
private |
warehouse of objects that have already been created
Definition at line 326 of file Factory.h.
Referenced by simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::apply(), and simcore::Factory< Prototype, PrototypePtr, PrototypeConstructorArgs >::make().