diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2012-09-05 18:51:26 +0200 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2012-09-05 18:51:26 +0200 |
commit | df2c44401f8dd736a903e73813e5f83fb15b36b6 (patch) | |
tree | b845f54b2dbb3f14dab435d2640c58b7b85e7975 /include/module | |
parent | 43aaf39cc828f4e1cec12a944560571993fb24f7 (diff) | |
download | crawler-df2c44401f8dd736a903e73813e5f83fb15b36b6.tar.gz crawler-df2c44401f8dd736a903e73813e5f83fb15b36b6.tar.bz2 |
split away util, logger, and module
made a liblogger
adapted all tests
Diffstat (limited to 'include/module')
-rwxr-xr-x | include/module/ModuleLoader.hpp | 262 | ||||
-rwxr-xr-x | include/module/ModuleRegistry.hpp | 190 |
2 files changed, 452 insertions, 0 deletions
diff --git a/include/module/ModuleLoader.hpp b/include/module/ModuleLoader.hpp new file mode 100755 index 0000000..a5416bb --- /dev/null +++ b/include/module/ModuleLoader.hpp @@ -0,0 +1,262 @@ +#ifndef __MODULELOADER_H +#define __MODULELOADER_H + +#include <vector> +#include <map> +#include <string> +#include <stdexcept> +#include <typeinfo> +#include <sstream> + +#ifndef _WIN32 +#include <dlfcn.h> +#else +#define WIN32_MEAN_AND_LEAN +#include <windows.h> +#include "win32/errormsg.hpp" +#endif + +#include "ModuleRegistry.hpp" + +#include "TypeList.hpp" +#include "TypeInfo.hpp" + +template< typename Interface, typename CtorParams = NullType > +struct Module { +#ifndef _WIN32 + void *handle; +#else + HMODULE handle; +#endif + ModuleRegistry< Interface, CtorParams > *registry; +}; + +template< typename Interface, typename CtorParams = NullType > +class BaseModuleLoader { + + public: + + typedef typename std::map<std::string, Module< Interface, CtorParams > > mapType; + + protected: + + mapType m_modules; + + public: + + BaseModuleLoader( const std::vector<std::string> files ) + { + Module< Interface, CtorParams> m; + + for( std::vector<std::string>::const_iterator it = files.begin( ); it != files.end( ); it++ ) { +#ifndef _WIN32 + m.handle = dlopen( it->c_str( ), RTLD_NOW ); +#else + m.handle = LoadLibrary( it->c_str( ) ); +#endif + if( !m.handle ) { +#ifndef _WIN32 + throw std::runtime_error( dlerror( ) ); +#else + std::ostringstream ss; + ss << "Module '" << *it << "' loading error: " << getLastError( ); + throw std::runtime_error( ss.str( ) ); +#endif + } + + std::string registryName = "registry_" + demangle( typeid( Interface ) ); + +#ifndef _WIN32 + m.registry = static_cast< ModuleRegistry< Interface, CtorParams > *>( dlsym( m.handle, registryName.c_str( ) ) ); +#else + m.registry = ( ModuleRegistry< Interface, CtorParams > *)( GetProcAddress( m.handle, registryName.c_str( ) ) ); +#endif + if( !m.registry ) { +#ifndef _WIN32 + dlclose( m.handle ); +#else + (void)FreeLibrary( m.handle ); +#endif + throw std::runtime_error( "missing module registry" ); + } + + m_modules.insert( std::make_pair( m.registry->name, m ) ); + } + } + + virtual ~BaseModuleLoader< Interface, CtorParams >( ) + { + for( typename mapType::iterator it = m_modules.begin( ); it != m_modules.end( ); it++ ) { + if( (*it).second.handle ) { +#ifndef _WIN32 + dlclose( (*it).second.handle ); +#else + (void)FreeLibrary( (*it).second.handle ); +#endif + (*it).second.handle = 0; + } + } + } + + void destroy( Interface *obj ) + { + 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; + +// no param + +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( ) ) { + std::ostringstream ss; + ss << "calling unknown constructor for class '" << subclass << "'"; + throw std::runtime_error( ss.str( ) ); + } + + Interface *obj = (*it).second.registry->create( ); + + std::string clazz = demangle( typeid( *obj ) ); + + BaseModuleLoader< Interface >::m_modules.insert( std::make_pair( clazz, (*it).second ) ); + + return obj; + } +}; + +// one param + +template< typename Interface, typename T1 > +class ModuleLoader< Interface, TYPELIST_1( T1 ) > : public BaseModuleLoader< Interface, TYPELIST_1( T1 ) > +{ + public: + + ModuleLoader< Interface, TYPELIST_1( T1 ) >( const std::vector<std::string> files ) + : BaseModuleLoader< Interface, TYPELIST_1( T1 ) >( files ) { } + + Interface *create( std::string subclass, T1 t1 ) + { + typename BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::m_modules.find( subclass ); + if( it == BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::m_modules.end( ) ) { + std::ostringstream ss; + ss << "calling unknown constructor for class '" << subclass << "'"; + throw std::runtime_error( ss.str( ) ); + } + + Interface *obj = (*it).second.registry->create( t1 ); + + std::string clazz = demangle( typeid( *obj ) ); + + BaseModuleLoader< Interface, TYPELIST_1( T1 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) ); + + return obj; + } +}; + +// two params + +template< typename Interface, typename T1, typename T2 > +class ModuleLoader< Interface, TYPELIST_2( T1, T2 ) > : public BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) > +{ + public: + + ModuleLoader< Interface, TYPELIST_2( T1, T2 ) >( const std::vector<std::string> files ) + : BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >( files ) { } + + Interface *create( std::string subclass, T1 t1, T2 t2 ) + { + typename BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::m_modules.find( subclass ); + if( it == BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::m_modules.end( ) ) { + std::ostringstream ss; + ss << "calling unknown constructor for class '" << subclass << "'"; + throw std::runtime_error( ss.str( ) ); + } + + Interface *obj = (*it).second.registry->create( t1, t2 ); + + std::string clazz = demangle( typeid( *obj ) ); + + BaseModuleLoader< Interface, TYPELIST_2( T1, T2 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) ); + + return obj; + } +}; + +// three params + +template< typename Interface, typename T1, typename T2, typename T3 > +class ModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) > : public BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) > +{ + public: + + ModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >( const std::vector<std::string> files ) + : BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >( files ) { } + + Interface *create( std::string subclass, T1 t1, T2 t2, T3 t3 ) + { + typename BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::m_modules.find( subclass ); + if( it == BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::m_modules.end( ) ) { + std::ostringstream ss; + ss << "calling unknown constructor for class '" << subclass << "'"; + throw std::runtime_error( ss.str( ) ); + } + + Interface *obj = (*it).second.registry->create( t1, t2, t3 ); + + std::string clazz = demangle( typeid( *obj ) ); + + BaseModuleLoader< Interface, TYPELIST_3( T1, T2, T3 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) ); + + return obj; + } +}; + +// four params + +template< typename Interface, typename T1, typename T2, typename T3, typename T4 > +class ModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) > : public BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) > +{ + public: + + ModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >( const std::vector<std::string> files ) + : BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >( files ) { } + + Interface *create( std::string subclass, T1 t1, T2 t2, T3 t3, T4 t4 ) + { + typename BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::mapType::const_iterator it = BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::m_modules.find( subclass ); + if( it == BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::m_modules.end( ) ) { + std::ostringstream ss; + ss << "calling unknown constructor for class '" << subclass << "'"; + throw std::runtime_error( ss.str( ) ); + } + + Interface *obj = (*it).second.registry->create( t1, t2, t3, t4 ); + + std::string clazz = demangle( typeid( *obj ) ); + + BaseModuleLoader< Interface, TYPELIST_4( T1, T2, T3, T4 ) >::m_modules.insert( std::make_pair( clazz, (*it).second ) ); + + return obj; + } +}; + +#endif diff --git a/include/module/ModuleRegistry.hpp b/include/module/ModuleRegistry.hpp new file mode 100755 index 0000000..e217092 --- /dev/null +++ b/include/module/ModuleRegistry.hpp @@ -0,0 +1,190 @@ +#ifndef __MODULEINTERFACE_H +#define __MODULEINTERFACE_H + +#include <string> + +#include "TypeList.hpp" + +template< typename Interface, typename CtorParams = NullType > +struct ModuleRegistry; + +template< typename Interface> +struct ModuleRegistry< Interface > { + std::string name; + Interface *(*create)( ); + void (*destroy)( Interface *obj ); + + ModuleRegistry( std::string _name, Interface *(*_create)( ), + void (*_destroy)( Interface *obj ) ) + : name( _name ), create( _create ), destroy( _destroy ) + { + } +}; + +template< typename Interface, typename P1 > +struct ModuleRegistry< Interface, TYPELIST_1( P1 ) > { + std::string name; + Interface *(*create)( P1 ); + void (*destroy)( Interface *obj ); + + ModuleRegistry( std::string _name, Interface *(*_create)( P1 ), + void (*_destroy)( Interface *obj ) ) + : name( _name ), create( _create ), destroy( _destroy ) + { + } +}; + +template< typename Interface, typename P1, typename P2 > +struct ModuleRegistry< Interface, TYPELIST_2( P1, P2 ) > { + std::string name; + Interface *(*create)( P1, P2 ); + void (*destroy)( Interface *obj ); + + ModuleRegistry( std::string _name, Interface *(*_create)( P1, P2 ), + void (*_destroy)( Interface *obj ) ) + : name( _name ), create( _create ), destroy( _destroy ) + { + } +}; + +template< typename Interface, typename P1, typename P2, typename P3 > +struct ModuleRegistry< Interface, TYPELIST_3( P1, P2, P3 ) > { + std::string name; + Interface *(*create)( P1, P2, P3 ); + void (*destroy)( Interface *obj ); + + ModuleRegistry( std::string _name, Interface *(*_create)( P1, P2, P3 ), + void (*_destroy)( Interface *obj ) ) + : name( _name ), create( _create ), destroy( _destroy ) + { + } +}; + +template< typename Interface, typename P1, typename P2, typename P3, typename P4 > +struct ModuleRegistry< Interface, TYPELIST_4( P1, P2, P3, P4 ) > { + std::string name; + Interface *(*create)( P1, P2, P3, P4 ); + void (*destroy)( Interface *obj ); + + ModuleRegistry( std::string _name, Interface *(*_create)( P1, P2, P3, P4 ), + void (*_destroy)( Interface *obj ) ) + : name( _name ), create( _create ), destroy( _destroy ) + { + } +}; + +#ifdef SHARED + +#ifndef _WIN32 +#define DLLEXPORT +#else +#define DLLEXPORT __declspec( dllexport ) +#endif + +// no param macro + +#define DECLARE_MODULE( baseClass ) \ + extern "C" DLLEXPORT ModuleRegistry<baseClass> registry ## _ ## baseClass; + +#define REGISTER_MODULE( name, baseClass, subClass ) \ +static baseClass *create( ) \ +{ \ + return new subClass( ); \ +} \ + \ +static void destroy( baseClass *obj ) \ +{ \ + delete obj; \ +} \ + \ +ModuleRegistry<baseClass> registry ## _ ## baseClass( name, &create, &destroy ); + +// 1 param macro + +#define DECLARE_MODULE_1( baseClass, T1 ) \ + extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_1( T1 ) > registry ## _ ## baseClass; + +#define REGISTER_MODULE_1( name, baseClass, subClass, T1 ) \ +static baseClass *create( T1 t1 ) \ +{ \ + return new subClass( t1 ); \ +} \ + \ +static void destroy( baseClass *obj ) \ +{ \ + delete obj; \ +} \ + \ +ModuleRegistry<baseClass, TYPELIST_1( T1 )> registry ## _ ## baseClass( name, &create, &destroy ); + +// 2 param macro + +#define DECLARE_MODULE_2( baseClass, T1, T2 ) \ + extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_2( T1, T2 ) > registry ## _ ## baseClass; + +#define REGISTER_MODULE_2( name, baseClass, subClass, T1, T2 ) \ +static baseClass *create( T1 t1, T2 t2 ) \ +{ \ + return new subClass( t1, t2 ); \ +} \ + \ +static void destroy( baseClass *obj ) \ +{ \ + delete obj; \ +} \ + \ +ModuleRegistry<baseClass, TYPELIST_2( T1, T2 )> registry ## _ ## baseClass( name, &create, &destroy ); + +// 3 param macro + +#define DECLARE_MODULE_3( baseClass, T1, T2, T3 ) \ + extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_3( T1, T2, T3 ) > registry ## _ ## baseClass; + +#define REGISTER_MODULE_3( name, baseClass, subClass, T1, T2, T3 ) \ +static baseClass *create( T1 t1, T2 t2, T3 t3 ) \ +{ \ + return new subClass( t1, t2, t3 ); \ +} \ + \ +static void destroy( baseClass *obj ) \ +{ \ + delete obj; \ +} \ + \ +ModuleRegistry<baseClass, TYPELIST_3( T1, T2, T3 )> registry ## _ ## baseClass( name, &create, &destroy ); + +// 4 param macro + +#define DECLARE_MODULE_4( baseClass, T1, T2, T3, T4 ) \ + extern "C" DLLEXPORT ModuleRegistry<baseClass, TYPELIST_4( T1, T2, T3, T4 ) > registry ## _ ## baseClass; + +#define REGISTER_MODULE_4( name, baseClass, subClass, T1, T2, T3, T4 ) \ +static baseClass *create( T1 t1, T2 t2, T3 t3, T4 t4 ) \ +{ \ + return new subClass( t1, t2, t3, t4 ); \ +} \ + \ +static void destroy( baseClass *obj ) \ +{ \ + delete obj; \ +} \ + \ +ModuleRegistry<baseClass, TYPELIST_4( T1, T2, T3, T4 )> registry ## _ ## baseClass( name, &create, &destroy ); + +#else // SHARED + +#define DECLARE_MODULE( baseClass ) +#define DECLARE_MODULE_1( baseClass, T1 ) +#define DECLARE_MODULE_2( baseClass, T1, T2 ) +#define DECLARE_MODULE_3( baseClass, T1, T2, T3 ) +#define DECLARE_MODULE_4( baseClass, T1, T2, T3, T4 ) + +#define REGISTER_MODULE( name, baseClass, subClass ) +#define REGISTER_MODULE_1( name, baseClass, subClass, T1 ) +#define REGISTER_MODULE_2( name, baseClass, subClass, T1, T2 ) +#define REGISTER_MODULE_3( name, baseClass, subClass, T1, T2, T3 ) +#define REGISTER_MODULE_4( name, baseClass, subClass, T1, T2, T3, T4 ) + +#endif // SHARED + +#endif // __MODULEINTERFACE_H |