Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

Generic Factories


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 ()

Detailed Description

Introduction

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.

Linking

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".

Plug-Ins

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.


Define Documentation

#define AT_Factory_Home   1
 

#define AT_FactorySymbolRef x_Name,
x_NumParam       x_g_f ## x_Name ## _ ## x_NumParam ## P_ref
 

AT_FactorySymbolRef?P macros create a name for symbols to be exported so that linking of factories can be forced into certain executables.

#define AT_HardLinkArrayElement x_Name,
x_NumParam       & AT_FactorySymbolRef(x_Name,x_NumParam),
 

AT_HardLinkArrayElement creates an entry to an list suitable for initializing an array

#define AT_HardLinkExtern x_Name,
x_NumParam       extern "C" { extern void * AT_FactorySymbolRef(x_Name,x_NumParam); };
 

AT_HardLinkExtern is a macro that provides an extern for the symbol that is generated when AT_Make*Factory* macros are used.

#define AT_MakeCUnitLink name       int AT_MakeCUnitLink_Name(name)[1];
 

#define AT_MakeCUnitLink_Name name       x_AT_CUnit_##name
 

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.

#define AT_MakeCUnitLinkExtern name       extern int AT_MakeCUnitLink_Name(name)[];
 

#define AT_MakeFactory0P x_Key,
x_Impl,
x_Interface,
x_KeyType   
 

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 ); };
The AT_MakeFactory?P macros create a factory for a given number of constructor paramaters.

#define AT_MakeFactory1P x_Key,
x_Impl,
x_Interface,
x_KeyType,
x_arg1   
 

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 ); };

#define AT_MakeFactory2P x_Key,
x_Impl,
x_Interface,
x_KeyType,
x_arg1,
x_arg2   
 

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 ); };

#define AT_MakeFactory3P x_Key,
x_Impl,
x_Interface,
x_KeyType,
x_arg1,
x_arg2,
x_arg3   
 

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 ); };

#define AT_MakeNamedFactory0P x_Name,
x_Key,
x_Impl,
x_Interface,
x_KeyType   
 

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 ); };
The AT_MakeNamedFactory?P macros create a factory for a given number of constructor paramaters - but the name is selectable so that an implementation may be registered in a number of factories.

#define AT_MakeNamedFactory1P x_Name,
x_Key,
x_Impl,
x_Interface,
x_KeyType,
x_arg1   
 

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 ); };

#define AT_MakeNamedFactory2P x_Name,
x_Key,
x_Impl,
x_Interface,
x_KeyType,
x_arg1,
x_arg2   
 

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 ); };

#define AT_MakeNamedFactory3P x_Name,
x_Key,
x_Impl,
x_Interface,
x_KeyType,
x_arg1,
x_arg2,
x_arg3   
 

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 ); };


Function Documentation

template<typename w_InterfaceType, typename w_KeyType, typename w_CreatorType>
FactoryRegister< w_InterfaceType, w_KeyType, w_CreatorType > & at::FactoryRegister< w_InterfaceType, w_KeyType, w_CreatorType >::Get   [static, inherited]
 

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.

template<typename w_KeyType>
AT_String KeyToStr const w_KeyType &    i_key
 

Convert the given key to a string for status reports or other uses.

Parameters:
i_key  is the key to convert to a string
Returns:
the string representation of the key

Generated for Austria by doxygen and MakeXS at Sun Oct 24 17:35:34 PDT 2004