From: <sg...@us...> - 2003-09-28 03:22:12
|
Update of /cvsroot/libfunutil/libfunutil/lib/s11n In directory sc8-pr-cvs1:/tmp/cvs-serv17332/lib/s11n Modified Files: ClassLoader.h DLLLoader.cpp DLLLoader.h Log Message: good night! Index: ClassLoader.h =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/lib/s11n/ClassLoader.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ClassLoader.h 27 Sep 2003 22:36:54 -0000 1.1 +++ ClassLoader.h 28 Sep 2003 03:21:57 -0000 1.2 @@ -33,6 +33,11 @@ */ template < class BaseType, class KeyType = std::string > class ClassLoader { + private: + ClassLoader( const ClassLoader & ); // intentionally unimpl + ClassLoader & operator=( const ClassLoader & ); // intentionally unimpl + typedef s11n::Instantiator < BaseType, KeyType > instantiator_type; + PathFinder m_path; public: typedef BaseType value_type; typedef KeyType key_type; @@ -93,11 +98,6 @@ return this->m_path; } - private: - typedef s11n::Instantiator < BaseType, KeyType > instantiator_type; -// ClassLoader( const ClassLoader & ); // intentionally unimpl -// ClassLoader & operator=( const ClassLoader & ); // intentionally unimpl - PathFinder m_path; }; Index: DLLLoader.cpp =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/lib/s11n/DLLLoader.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- DLLLoader.cpp 28 Sep 2003 01:35:30 -0000 1.2 +++ DLLLoader.cpp 28 Sep 2003 03:21:57 -0000 1.3 @@ -29,16 +29,16 @@ object has a registry, else false. It only runs the registry the first time it is passed a given pointer. */ - bool check_for_registry( void * soh ) + bool check_for_registry( void * soh, const char * key ) { if( ! soh ) return false; const char * funcname = "DLLLoader_bootstrap"; - typedef void (*registry)(); - typedef std::map<void *,unsigned long int> done_map; + typedef void (*registry)( const char * ); + typedef std::map<void *,bool> done_map; static done_map done; if( done[soh] ) return true; //COUT << "check_for_registry(" << std::hex << soh << ")"<<std::endl; - done[soh] = 1; + done[soh] = true; registry reg; reg = (registry) dlsym( soh, funcname ); if( ! reg ) @@ -46,7 +46,7 @@ //CERR << "no " << funcname << "() found in " << std::hex << soh << "" << std::endl; return false; } - reg(); + reg( key ? key : "" ); return true; } @@ -65,24 +65,32 @@ if( ! soh_main ) { soh_main = dlopen( NULL, RTLD_NOW | RTLD_GLOBAL ); - check_for_registry( soh_main ); + check_for_registry( soh_main, "DLLLoader bootstrap" ); } } DLLLoader::~DLLLoader() { - if( 0 == --DLLLoader_inst_count ) { - dlclose( soh_main ); + COUT << "DLLoader::~DLLoader " << std::endl; + DLLLoader::symbol_map_type & smap = DLLLoader::symbol_map(); + smap.erase( smap.begin(), smap.end() ); + DLLLoader::soh_map_type & map = DLLLoader::soh_map(); DLLLoader::soh_map_type::iterator it = map.begin(); DLLLoader::soh_map_type::iterator et = map.end(); for( ; it != et; ++it ) { - //COUT << "Closing DLL: " << std::hex <<(*it).second<<std::endl; - dlclose( (*it).second ); + if( NULL != (*it).second ) + { + COUT << "Closing DLL: " << std::hex <<(*it).second<<""<<std::endl; + dlclose( (*it).second ); + } + map.erase( it ); } + + dlclose( soh_main ); } }; @@ -106,21 +114,33 @@ //COUT << "load("<<key<<")"<<std::endl; typedef ThisType::value_type CHT; CHT *ch = NULL; - ch = this->ParentClass::load( key ); + ch = this->ParentClass::load( key ); // if the parent can handle it, great. if ( ch ) return ch; void * soh = 0; std::string xlated = key; // key, translated to remove namespace part (because :: is not filesystem-friendly). std::string path = key; - DLLLoader::soh_map_type & map = DLLLoader::soh_map(); - DLLLoader::soh_map_type::iterator it = map.find(key); - if( map.end() != it ) + + DLLLoader::instantiator_func instantiator = 0; + DLLLoader::symbol_map_type & symmap = DLLLoader::symbol_map(); + DLLLoader::symbol_map_type::iterator sit = symmap.find(key); + if( symmap.end() != sit ) { - soh = (*it).second; - if( NULL == soh ) return NULL; + instantiator = (*sit).second; + if( NULL == instantiator ) return NULL; + return instantiator( key.c_str() ); } - else - { + + DLLLoader::soh_map_type & map = DLLLoader::soh_map(); + +#define MARK_AS_EVIL map[key] = NULL; symmap[key] = NULL; +// ^^^ marks an entry as no-go, so we won't re-use it later. + + DLLLoader::soh_map_type::iterator it = map.find(key); + if( map.end() == it ) + { // it's not in our map. Let's look for a file: + + // strip namespace part from the file (it's not filesystem-friendly in some places) std::string::size_type colon = xlated.rfind( ":" ); if( std::string::npos != colon ) { @@ -129,69 +149,44 @@ path = this->path().find( xlated ); if ( path.empty() ) { + MARK_AS_EVIL; CERR << "Neither in-built class nor DLL found for "<<key<<" ["<<xlated<<"]. path=["<<this->path()<<"]"<<std::endl; return NULL; } - it = map.find(path); - //COUT << "load("<<key<<" ["<<xlated<<"]) dll path="<<path<<std::endl; - } - - if( map.end() != it ) - { - soh = (*it).second; - //COUT << "cached entry ["<<path<<"]: " << std::hex << soh << std::endl; - if( NULL == soh ) return NULL; - } - else - { soh = dlopen( path.c_str(), RTLD_NOW | RTLD_GLOBAL ); - if( ! soh ) + if( ! soh ) { COUT << "error? dlerror() says: " << dlerror() << std::endl; soh = soh_main; } - //COUT << "key="<<key<<" ["<<xlated<<"], path=["<<path<<"], soh = " << std::hex << soh << ", dll path="<<path<<std::endl; - if( ! soh ) - { - map[path] = map[key] = (void *)NULL; - return NULL; - } - map[path] = map[key] = soh; + map[key] = soh; + //COUT << "load("<<key<<" ["<<xlated<<"]) dll path="<<path<<std::endl; } - - if( check_for_registry( soh ) ) + else + { // we have a dlopen handle already: + soh = (*it).second; + //COUT << "cached entry ["<<path<<"]: " << std::hex << soh << std::endl; + if( NULL == soh ) return NULL; + } + + if( check_for_registry( soh, key.c_str() ) ) { // give parent another chance. registration may have assigned a factory. ch = this->ParentClass::load( key ); if( ch ) return ch; } - DLLLoader::instantiator_func instantiator = 0; + //COUT << "key="<<key<<" ["<<xlated<<"], path=["<<path<<"], soh = " << std::hex << soh << ", dll path="<<path<<std::endl; + //COUT << "mapping ["<<key<<"] to "<<std::hex<<soh<<""<<std::endl; - DLLLoader::symbol_map_type & symmap = DLLLoader::symbol_map(); - DLLLoader::symbol_map_type::iterator sit = symmap.find(soh); - if( symmap.end() != sit ) + std::string inst_funcname = "new_" + xlated; + if( (instantiator = (instantiator_func) dlsym( soh, inst_funcname.c_str() )) ) { - instantiator = (*sit).second; + symmap[key] = instantiator; } else { - //const char * inst_funcname = "instantiateSerializable"; - std::string inst_funcname = "new_" + xlated; - if( (instantiator = (instantiator_func) dlsym( soh, inst_funcname.c_str() )) ) - { - symmap[soh] = instantiator; - } - else - { - symmap[soh] = NULL; - } - } - - if( ! instantiator ) - { - //CERR << "error? dlerror() says: " <<dlerror() << std::endl; if( soh && (soh_main != soh) ) dlclose( soh ); - map[path] = map[key] = (void *)NULL; + MARK_AS_EVIL; return NULL; } Index: DLLLoader.h =================================================================== RCS file: /cvsroot/libfunutil/libfunutil/lib/s11n/DLLLoader.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- DLLLoader.h 28 Sep 2003 01:35:30 -0000 1.2 +++ DLLLoader.h 28 Sep 2003 03:21:57 -0000 1.3 @@ -47,16 +47,19 @@ Define an extern "C" function with this sigature: - void DLLLoader_bootstrap(); + void DLLLoader_bootstrap( const char * ); - If that function exists it is called when the class is loaded. - This gives the class a chance to register factories for other - names of itself or for dependent classes. + If that function exists it is called when the class is + loaded. This gives the class a chance to register + factories for other names of itself or for dependent + classes. It is passed the name of the symbol used to + initialize the search for it, which might be an empty + string or NULL. Example: extern "C" { - void DLLLoader_bootstrap() + void DLLLoader_bootstrap( const char * ) { s11n::register_serializable_type<foo::FooClass>("FooClass"); s11n::register_serializable_type<foo::FooClass>("foo::FooClass"); @@ -73,14 +76,27 @@ typedef s11n::ClassLoader < s11n::Serializable, std::string > ParentClass; protected: typedef s11n::Serializable * (*instantiator_func)( const char * ); + /** + Maps strings (raw keys and translated paths) to + dlopen() handles. + */ typedef std::map<std::string,void *> soh_map_type; - typedef std::map<void *,instantiator_func> symbol_map_type; /** - Returns a map of keys to DLL handles (void *). + Maps dlopen() handles to instantiator_funcs. These + functions are normally created via + S11N_INSTANTIATOR(). + + todo: change this to map strings to instantiators, to + save a lot of lookups in load(). + */ + //typedef std::map<void *,instantiator_func> symbol_map_type; + typedef std::map<std::string,instantiator_func> symbol_map_type; + /** + Returns a map of keys to DLL handles. */ static soh_map_type & soh_map(); /** - Returns a map of keys to DLL handles (void *). + Returns a map of DLL handles to functions. */ static symbol_map_type & symbol_map(); |