Compounds | |
| class | Creator0P |
| class | Creator1P |
| class | Creator2P |
| class | Creator3P |
| class | CreatorImpl0P |
| class | CreatorImpl1P |
| class | CreatorImpl2P |
| class | CreatorImpl3P |
| class | DKy |
| class | Factory_Base |
| class | FactoryEntryLocator_Base |
| class | FactoryImpl0P |
| class | FactoryImpl1P |
| class | FactoryImpl2P |
| class | FactoryImpl3P |
| class | FactoryRegister |
| class | FactoryRegisterBase |
| class | FactoryRegisterRegistry |
| class | FactoryRegistryEntry |
| class | FactoryTraits |
| class | Wrapper_Basic |
Defines | |
| #define | AT_Factory_Home 1 |
| #define | AT_FactorySymbolRef(x_Name, x_NumParam) x_g_f ## x_Name ## _ ## x_NumParam ## P_ref |
| #define | AT_MakeFactory0P(x_Key, x_Impl, x_Interface, x_KeyType) |
| #define | AT_MakeFactory1P(x_Key, x_Impl, x_Interface, x_KeyType, x_arg1) |
| #define | AT_MakeFactory2P(x_Key, x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2) |
| #define | AT_MakeFactory3P(x_Key, x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2, x_arg3) |
| #define | AT_MakeNamedFactory0P(x_Name, x_Key, x_Impl, x_Interface, x_KeyType) |
| #define | AT_MakeNamedFactory1P(x_Name, x_Key, x_Impl, x_Interface, x_KeyType, x_arg1) |
| #define | AT_MakeNamedFactory2P(x_Name, x_Key, x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2) |
| #define | AT_MakeNamedFactory3P(x_Name, x_Key, x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2, x_arg3) |
| #define | AT_MakeCUnitLink_Name(name) x_AT_CUnit_##name |
| #define | AT_MakeCUnitLink(name) int AT_MakeCUnitLink_Name(name)[1]; |
| #define | AT_MakeCUnitLinkExtern(name) extern int AT_MakeCUnitLink_Name(name)[]; |
| #define | AT_HardLinkExtern(x_Name, x_NumParam) extern "C" { extern void * AT_FactorySymbolRef(x_Name,x_NumParam); }; |
| #define | AT_HardLinkArrayElement(x_Name, x_NumParam) & AT_FactorySymbolRef(x_Name,x_NumParam), |
Functions | |
| template<typename w_KeyType> AT_String | KeyToStr (const w_KeyType &i_key) |
| FactoryRegister & | Get () |
This module supports the factory pattern in a generic C++ way. The Austria Factory module supports generic interfaces but also supports generic construction paramters. This can be used to support plug-ins from shared libraries or DLL's.
An Austria factory registers itself with the in-process factory registry at initialization time. This means that factories are not useful until after main is called.
There are a number of issues to be aware of with austria factories. Because the mechanism for registering factories is truly generic, the system linker may not be able to observe a requirement to link in a factory from a factory library. Austria's factories provide a simple mechanism to pull in factories.
To provide a mechanism that allows for hard-linking an unfortunate side-effect is that the final factory name will tanscend namespaces. The factory name is determined at the invocation of the AT_MakeFactory* or the AT_MakeNamedFactory* macros. For AT_MakeFactory*, the name is derived from the implementation class name while AT_MakeNamedFactory* allows the use of any valid C language identifier as a name. Factory names are only relevant in the case where hard linking is important. The bottom line is that the choice of factory name must be such that they do not collide with factories anywhere else regardless of namespace or interface names.
The generic method for hard-linking factories is to provide a list of all the factories that are required in an application specifc "hard_linked.cpp" file in the form of a macro named HardLink. The code below shows a simple example.
// this file is hard_link.cpp
define HardLink(A) \
A(FactoryName,0) \
A(FactoryFoo,2) \
A(FactoryBar,1) \
// Inlcude the factory hard link magic
// THIS MUST BE INCLUDED AFTER HardLink is defined
include "at_factory_link.h"
The file "hard_link.cpp" above will create references to the factory named "FactoryName" taking 0 constructor parameters, the factory named "FactoryFoo" taking 2 constructor parameters etc. Linking the result of this file into the application will cause the linker to pull in the factories with the names specified in the HardLink macro above. There is no limit to the number of hard_link.cpp files in an application but a different name for the resulting hard linked symbol will be required. The macro AT_HardLinkSymbolName may be provided before including at_factory_link.h to change the name of the resulting symbol. Some linkers may still deduce that AT_HardLinkSymbolName is not being used. In this case, there are 2 possible solutions. The first is to use a linker option that specifically defines the hard-link symbol as required, or to simply reference the symbol in your code using somthing like this:
// this file is hard_link.cpp
define HardLink(A) \
A(FactoryName,0) \
A(FactoryFoo,2) \
A(FactoryBar,1) \
// Inlcude the factory hard link magic
// THIS MUST BE INCLUDED AFTER HardLink is defined
include "at_factory_link.h"
bool SmartLinkerWorkAround( int i_n )
{
return AT_HardLinkSymbolName[i_n] == 0;
}
Followed by placing a call to SmartLinkerWorkAround in main for example.
// this is main
extern bool SmartLinkerWorkAround( int i_n );
int main()
{
SmartLinkerWorkAround(0);
.... application code.
}
The alternative is to use the linker to force the linking. On Visual Studio, the linker option is "/INCLUDE:symbol". The GNU linker supports a similar option "--undefined=SYMBOL".
Austria factories may also be used with dynamic libraries. This issue to be careful here is to make sure that the factory registry method is linked in only one place. The registration of new libraries is (currently) not thread safe, so if factory registries are being modified (by loading or unloading a new .so or .dll) while they are also being searched, unpredictable issues will occur. The thread safety issue will be addressed later.
|
|
|
|
|
AT_FactorySymbolRef?P macros create a name for symbols to be exported so that linking of factories can be forced into certain executables. |
|
|
AT_HardLinkArrayElement creates an entry to an list suitable for initializing an array |
|
|
AT_HardLinkExtern is a macro that provides an extern for the symbol that is generated when AT_Make*Factory* macros are used. |
|
|
|
|
|
AT_MakeCUnitLink is used to define a symbol for linking a compile unit. Since factories are loosly linked, it may be impossible to force a linker to link them into an executable. Using these macros, a compile unit may be forced to link in. |
|
|
|
|
|
Value: FactoryImpl0P<x_Impl, x_Interface, x_KeyType> \
x_g_f ## x_Impl ## _0P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key ); \
extern "C" { void * AT_FactorySymbolRef(x_Impl,0) = static_cast<void *>( & x_g_f ## x_Impl ## _0P ); }; |
|
|
Value: FactoryImpl1P<x_Impl, x_Interface, x_KeyType, x_arg1> \
x_g_f ## x_Impl ## _1P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key ); \
extern "C" { void * AT_FactorySymbolRef(x_Impl,1) = static_cast<void *>( & x_g_f ## x_Impl ## _1P ); }; |
|
|
Value: FactoryImpl2P<x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2> \
x_g_f ## x_Impl ## _2P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key ); \
extern "C" { void * AT_FactorySymbolRef(x_Impl,2) = static_cast<void *>( & x_g_f ## x_Impl ## _2P ); }; |
|
|
Value: FactoryImpl3P<x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2, x_arg3> \
x_g_f ## x_Impl ## _3P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key ); \
extern "C" { void * AT_FactorySymbolRef(x_Impl,3) = static_cast<void *>( & x_g_f ## x_Impl ## _3P ); }; |
|
|
Value: FactoryImpl0P<x_Impl, x_Interface, x_KeyType> \
x_g_f ## x_Name ## _0P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key " " # x_Name ); \
extern "C" { void * AT_FactorySymbolRef(x_Name,0) = static_cast<void *>( & x_g_f ## x_Name ## _0P ); }; |
|
|
Value: FactoryImpl1P<x_Impl, x_Interface, x_KeyType, x_arg1> \
x_g_f ## x_Name ## _1P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key " " # x_Name ); \
extern "C" { void * AT_FactorySymbolRef(x_Name,1) = static_cast<void *>( & x_g_f ## x_Name ## _1P ); }; |
|
|
Value: FactoryImpl2P<x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2> \
x_g_f ## x_Name ## _2P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key " " # x_Name ); \
extern "C" { void * AT_FactorySymbolRef(x_Name,2) = static_cast<void *>( & x_g_f ## x_Name ## _2P ); }; |
|
|
Value: FactoryImpl3P<x_Impl, x_Interface, x_KeyType, x_arg1, x_arg2, x_arg3> \
x_g_f ## x_Name ## _3P( x_Key, __FILE__, __LINE__, # x_Interface " " # x_Impl " " # x_Key " " # x_Name ); \
extern "C" { void * AT_FactorySymbolRef(x_Name,3) = static_cast<void *>( & x_g_f ## x_Name ## _3P ); }; |
|
|||||||||
|
This method will return a singleton FactoryRegister for this type set of template parameters. The library that contains the instantiation of this method is the one that contains the registry. To make sure that all factories use a single registry, it's important to be selective of where this method is instantiated. The AT_Factory_Home macro is intended to create a way to isolate which compilation units contain the definition and which do not. |
|
||||||||||
|
Convert the given key to a string for status reports or other uses.
|
Generated for Austria by
and
MakeXS at Sun Oct 24 17:35:34 PDT 2004