OpenWalnut 1.3.1
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <algorithm> 00026 #include <iostream> 00027 #include <set> 00028 #include <string> 00029 #include <typeinfo> 00030 #include <vector> 00031 00032 #include "../common/WLogger.h" 00033 #include "combiner/WApplyCombiner.h" 00034 #include "exceptions/WPrototypeNotUnique.h" 00035 #include "exceptions/WPrototypeUnknown.h" 00036 #include "WModule.h" 00037 #include "WModuleCombiner.h" 00038 #include "WModuleFactory.h" 00039 00040 // factory instance as singleton 00041 boost::shared_ptr< WModuleFactory > WModuleFactory::m_instance = boost::shared_ptr< WModuleFactory >(); 00042 00043 WModuleFactory::WModuleFactory(): 00044 m_prototypes(), 00045 m_moduleLoader() 00046 { 00047 // initialize members 00048 } 00049 00050 WModuleFactory::~WModuleFactory() 00051 { 00052 // cleanup 00053 } 00054 00055 void WModuleFactory::load() 00056 { 00057 // load modules 00058 WLogger::getLogger()->addLogMessage( "Loading Modules", "ModuleFactory", LL_INFO ); 00059 00060 // operation must be exclusive 00061 PrototypeSharedContainerType::WriteTicket l = m_prototypes.getWriteTicket(); 00062 00063 // Load the dynamic modules here: 00064 m_moduleLoader.load( l ); 00065 00066 // initialize every module in the set 00067 std::set< std::string > names; // helper to find duplicates 00068 PrototypeContainerIteratorType listIter = l->get().begin(); 00069 while( listIter != l->get().end() ) 00070 { 00071 WLogger::getLogger()->addLogMessage( "Initializing module prototype: \"" + ( *listIter )->getName() + "\"", "ModuleFactory", LL_DEBUG ); 00072 00073 // that should not happen. Names should not occur multiple times since they are unique 00074 if( names.count( ( *listIter )->getName() ) ) 00075 { 00076 WLogger::getLogger()->addLogMessage( std::string( "Module \"" + ( *listIter )->getName() + 00077 "\" is not unique. Modules have to have a unique name. Ignoring this module." ), 00078 "ModuleFactory", LL_ERROR ); 00079 // we remove the module from the prototype list 00080 l->get().erase( listIter++ ); 00081 continue; 00082 } 00083 else 00084 { 00085 names.insert( ( *listIter )->getName() ); 00086 initializeModule( ( *listIter ) ); 00087 ++listIter; 00088 } 00089 } 00090 WLogger::getLogger()->addLogMessage( "Loading Modules Done", "ModuleFactory", LL_INFO ); 00091 } 00092 00093 bool WModuleFactory::isPrototype( boost::shared_ptr< WModule > module ) 00094 { 00095 // for this a read lock is sufficient, gets unlocked if it looses scope 00096 PrototypeSharedContainerType::ReadTicket l = getModuleFactory()->m_prototypes.getReadTicket(); 00097 return getModuleFactory()->checkPrototype( module, l ); 00098 } 00099 00100 bool WModuleFactory::checkPrototype( boost::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket ) 00101 { 00102 return ( ticket->get().count( module ) != 0 ); 00103 } 00104 00105 boost::shared_ptr< WModule > WModuleFactory::create( boost::shared_ptr< WModule > prototype ) 00106 { 00107 wlog::debug( "ModuleFactory" ) << "Creating new instance of prototype \"" << prototype->getName() << "\"."; 00108 00109 // for this a read lock is sufficient, gets unlocked if it looses scope 00110 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00111 00112 // ensure this one is a prototype and nothing else 00113 if( !checkPrototype( prototype, l ) ) 00114 { 00115 throw WPrototypeUnknown( std::string( "Could not clone module \"" + prototype->getName() + "\" since it is no prototype." ) ); 00116 } 00117 00118 // explicitly unlock 00119 l.reset(); 00120 00121 // call prototypes factory function 00122 boost::shared_ptr< WModule > clone = boost::shared_ptr< WModule >( prototype->factory() ); 00123 clone->setLocalPath( prototype->getLocalPath() ); // prototype and clone have the same local path. 00124 initializeModule( clone ); 00125 00126 return clone; 00127 } 00128 00129 void WModuleFactory::initializeModule( boost::shared_ptr< WModule > module ) 00130 { 00131 module->initialize(); 00132 } 00133 00134 boost::shared_ptr< WModuleFactory > WModuleFactory::getModuleFactory() 00135 { 00136 if( !m_instance ) 00137 { 00138 m_instance = boost::shared_ptr< WModuleFactory >( new WModuleFactory() ); 00139 } 00140 00141 return m_instance; 00142 } 00143 00144 00145 const boost::shared_ptr< WModule > WModuleFactory::isPrototypeAvailable( std::string name ) 00146 { 00147 // for this a read lock is sufficient, gets unlocked if it looses scope 00148 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00149 00150 // find first and only prototype (ensured during load()) 00151 boost::shared_ptr< WModule > ret = boost::shared_ptr< WModule >(); 00152 for( std::set< boost::shared_ptr< WModule > >::const_iterator listIter = l->get().begin(); listIter != l->get().end(); 00153 ++listIter ) 00154 { 00155 if( ( *listIter )->getName() == name ) 00156 { 00157 ret = ( *listIter ); 00158 break; 00159 } 00160 } 00161 00162 return ret; 00163 } 00164 00165 const boost::shared_ptr< WModule > WModuleFactory::getPrototypeByName( std::string name ) 00166 { 00167 boost::shared_ptr< WModule > ret = isPrototypeAvailable( name ); 00168 00169 // if not found -> throw 00170 if( ret == boost::shared_ptr< WModule >() ) 00171 { 00172 throw WPrototypeUnknown( std::string( "Could not find prototype \"" + name + "\"." ) ); 00173 } 00174 00175 return ret; 00176 } 00177 00178 const boost::shared_ptr< WModule > WModuleFactory::getPrototypeByInstance( boost::shared_ptr< WModule > instance ) 00179 { 00180 return getPrototypeByName( instance->getName() ); 00181 } 00182 00183 std::vector< WModule::ConstSPtr > WModuleFactory::getPrototypesByType( MODULE_TYPE type ) 00184 { 00185 std::vector< WModule::ConstSPtr > ret; 00186 00187 // for this a read lock is sufficient, gets unlocked if it looses scope 00188 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00189 00190 // find first and only prototype (ensured during load()) 00191 for( std::set< boost::shared_ptr< WModule > >::const_iterator listIter = l->get().begin(); listIter != l->get().end(); 00192 ++listIter ) 00193 { 00194 if( ( *listIter )->getType() == type ) 00195 { 00196 ret.push_back( *listIter ); 00197 } 00198 } 00199 00200 return ret; 00201 } 00202 00203 WModuleFactory::PrototypeSharedContainerType::ReadTicket WModuleFactory::getPrototypes() const 00204 { 00205 return m_prototypes.getReadTicket(); 00206 } 00207 00208 WCombinerTypes::WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost::shared_ptr< WModule > module ) 00209 { 00210 WCombinerTypes::WCompatiblesList compatibles; 00211 00212 // for this a read lock is sufficient, gets unlocked if it looses scope 00213 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00214 00215 // has the module an output? If not, return. 00216 bool addModulesWithoutInput = !module; 00217 00218 if( addModulesWithoutInput ) 00219 { 00220 // First, add all modules with no input connector. 00221 for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end(); 00222 ++listIter ) 00223 { 00224 // get connectors of this prototype 00225 WModule::InputConnectorList pcons = ( *listIter )->getInputConnectors(); 00226 if( pcons.size() == 0 ) 00227 { 00228 // the modules which match every time need their own groups 00229 WCombinerTypes::WOneToOneCombiners lComp; 00230 00231 // NOTE: it is OK here to use the variable module even if it is NULL as the combiner in this case only adds the specified module 00232 lComp.push_back( boost::shared_ptr< WApplyCombiner >( new WApplyCombiner( module, "", *listIter, "" ) ) ); 00233 00234 // add this list 00235 compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) ); 00236 } 00237 } 00238 } 00239 00240 // if NULL was specified, only return all modules without any inputs 00241 if( module ) 00242 { 00243 // go through every prototype 00244 for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end(); 00245 ++listIter ) 00246 { 00247 WCombinerTypes::WOneToOneCombiners lComp = WApplyCombiner::createCombinerList< WApplyCombiner >( module, ( *listIter ) ); 00248 00249 // add the group 00250 if( lComp.size() != 0 ) 00251 { 00252 compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) ); 00253 } 00254 } 00255 } 00256 00257 // unlock. No locking needed for further steps. 00258 l.reset(); 00259 00260 // sort the compatibles 00261 std::sort( compatibles.begin(), compatibles.end(), WCombinerTypes::compatiblesSort ); 00262 00263 return compatibles; 00264 } 00265 00266 WCombinerTypes::WCompatiblesList WModuleFactory::getAllPrototypes() 00267 { 00268 WCombinerTypes::WCompatiblesList compatibles; 00269 00270 // for this a read lock is sufficient, gets unlocked if it looses scope 00271 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00272 00273 // Add all modules. 00274 for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end(); 00275 ++listIter ) 00276 { 00277 // the modules which match every time need their own groups 00278 WCombinerTypes::WOneToOneCombiners lComp; 00279 00280 // NOTE: it is OK here to use the variable module even if it is NULL as the combiner in this case only adds the specified module 00281 lComp.push_back( boost::shared_ptr< WApplyCombiner >( new WApplyCombiner( *listIter ) ) ); 00282 00283 // add this list 00284 compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) ); 00285 } 00286 00287 // unlock. No locking needed for further steps. 00288 l.reset(); 00289 00290 // sort the compatibles 00291 std::sort( compatibles.begin(), compatibles.end(), WCombinerTypes::compatiblesSort ); 00292 00293 return compatibles; 00294 } 00295