diff options
Diffstat (limited to 'src/ModuleLoader.hpp')
-rw-r--r-- | src/ModuleLoader.hpp | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/src/ModuleLoader.hpp b/src/ModuleLoader.hpp index 1a89d38..524a0e1 100644 --- a/src/ModuleLoader.hpp +++ b/src/ModuleLoader.hpp @@ -14,29 +14,28 @@ #include "TypeList.hpp" #include "TypeInfo.hpp" -template< typename Interface > +template< typename Interface, typename CtorParams = NullType > struct Module { void *handle; - ModuleRegistry<Interface> *registry; + ModuleRegistry< Interface, CtorParams > *registry; }; -template< typename Interface > -class ModuleLoader { +template< typename Interface, typename CtorParams = NullType > +class BaseModuleLoader { + + public: - typedef typename std::map<std::string, Module< Interface > > mapType; + typedef typename std::map<std::string, Module< Interface, CtorParams > > mapType; - protected: + protected: + mapType m_modules; - + public: - - ModuleLoader<Interface>( ) - { - } - - ModuleLoader<Interface>( const std::vector<std::string> files ) + + BaseModuleLoader( const std::vector<std::string> files ) { - Module<Interface> m; + Module< Interface, CtorParams> m; for( std::vector<string>::const_iterator it = files.begin( ); it != files.end( ); it++ ) { m.handle = dlopen( it->c_str( ), RTLD_NOW ); @@ -46,7 +45,7 @@ class ModuleLoader { std::string registryName = "registry_" + demangle( typeid( Interface ) ); - m.registry = static_cast<ModuleRegistry<Interface> *>( dlsym( m.handle, registryName.c_str( ) ) ); + m.registry = static_cast< ModuleRegistry< Interface, CtorParams > *>( dlsym( m.handle, registryName.c_str( ) ) ); if( !m.registry ) { dlclose( m.handle ); throw std::runtime_error( "missing module registry" ); @@ -56,7 +55,7 @@ class ModuleLoader { } } - ~ModuleLoader<Interface>( ) + virtual ~BaseModuleLoader< Interface, CtorParams >( ) { for( typename mapType::iterator it = m_modules.begin( ); it != m_modules.end( ); it++ ) { if( (*it).second.handle ) { @@ -65,11 +64,35 @@ class ModuleLoader { } } } - - Interface *create( std::string subclass ) + + void destroy( Interface *obj ) { - typename mapType::const_iterator it = m_modules.find( subclass ); + std::string clazz = demangle( typeid( *obj ) ); + + typename mapType::const_iterator it = m_modules.find( clazz ); if( it == m_modules.end( ) ) { + throw std::runtime_error( "calling unknown destructor" ); + } + + (*it).second.registry->destroy( obj ); + } +}; + +template< typename Interface, typename CtorParams = NullType > +class ModuleLoader; + +template< typename Interface > +class ModuleLoader< Interface, NullType > : public BaseModuleLoader< Interface, NullType > +{ + public: + + ModuleLoader< Interface >( const std::vector<std::string> files ) + : BaseModuleLoader< Interface >(files ) { } + + Interface *create( std::string subclass ) + { + typename BaseModuleLoader< Interface >::mapType::const_iterator it = BaseModuleLoader< Interface >::m_modules.find( subclass ); + if( it == BaseModuleLoader< Interface >::m_modules.end( ) ) { throw std::runtime_error( "calling unknown constructor" ); } @@ -77,21 +100,34 @@ class ModuleLoader { std::string clazz = demangle( typeid( *obj ) ); - m_modules.insert( std::make_pair( clazz, (*it).second ) ); + BaseModuleLoader< Interface >::m_modules.insert( std::make_pair( clazz, (*it).second ) ); return obj; } - - void destroy( Interface *obj ) +}; + +template< typename Interface, typename P1 > +class ModuleLoader< Interface, TYPELIST_1( P1 ) > : public BaseModuleLoader< Interface, TYPELIST_1( P1 ) > +{ + public: + + ModuleLoader< Interface, TYPELIST_1( P1 ) >( const std::vector<std::string> files ) + : BaseModuleLoader< Interface, TYPELIST_1( P1 ) >( files ) { } + + Interface *create( std::string subclass, P1 p1 ) { + typename BaseModuleLoader< Interface, TYPELIST_1( P1 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_1( P1 ) >::m_modules.find( subclass ); + if( it == BaseModuleLoader< Interface, TYPELIST_1( P1 ) >::m_modules.end( ) ) { + throw std::runtime_error( "calling unknown constructor" ); + } + + Interface *obj = (*it).second.registry->create( p1 ); + std::string clazz = demangle( typeid( *obj ) ); - typename mapType::const_iterator it = m_modules.find( clazz ); - if( it == m_modules.end( ) ) { - throw std::runtime_error( "calling unknown destructor" ); - } + BaseModuleLoader< Interface, TYPELIST_1( P1 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) ); - (*it).second.registry->destroy( obj ); + return obj; } }; |