summaryrefslogtreecommitdiff
path: root/include/module
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2012-09-05 18:51:26 +0200
committerAndreas Baumann <abaumann@yahoo.com>2012-09-05 18:51:26 +0200
commitdf2c44401f8dd736a903e73813e5f83fb15b36b6 (patch)
treeb845f54b2dbb3f14dab435d2640c58b7b85e7975 /include/module
parent43aaf39cc828f4e1cec12a944560571993fb24f7 (diff)
downloadcrawler-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-xinclude/module/ModuleLoader.hpp262
-rwxr-xr-xinclude/module/ModuleRegistry.hpp190
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