OpenWalnut 1.2.5
|
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 m_prototypeAccess = m_prototypes.getWriteTicket(); 00062 00063 // Load the dynamic modules here: 00064 m_moduleLoader.load( m_prototypeAccess ); 00065 00066 // unlock as read lock is sufficient for the further steps 00067 m_prototypeAccess.reset(); 00068 00069 // for this a read lock is sufficient, gets unlocked if it looses scope 00070 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00071 00072 // initialize every module in the set 00073 std::set< std::string > names; // helper to find duplicates 00074 for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end(); 00075 ++listIter ) 00076 { 00077 WLogger::getLogger()->addLogMessage( "Initializing module prototype: \"" + ( *listIter )->getName() + "\"", "ModuleFactory", LL_DEBUG ); 00078 00079 // that should not happen. Names should not occur multiple times since they are unique 00080 if( names.count( ( *listIter )->getName() ) ) 00081 { 00082 throw WPrototypeNotUnique( std::string( "Module \"" + ( *listIter )->getName() 00083 + "\" is not unique. Modules have to have a unique name." ) ); 00084 } 00085 names.insert( ( *listIter )->getName() ); 00086 00087 initializeModule( ( *listIter ) ); 00088 } 00089 } 00090 00091 bool WModuleFactory::isPrototype( boost::shared_ptr< WModule > module ) 00092 { 00093 // for this a read lock is sufficient, gets unlocked if it looses scope 00094 PrototypeSharedContainerType::ReadTicket l = getModuleFactory()->m_prototypes.getReadTicket(); 00095 return getModuleFactory()->checkPrototype( module, l ); 00096 } 00097 00098 bool WModuleFactory::checkPrototype( boost::shared_ptr< WModule > module, PrototypeSharedContainerType::ReadTicket ticket ) 00099 { 00100 return ( ticket->get().count( module ) != 0 ); 00101 } 00102 00103 boost::shared_ptr< WModule > WModuleFactory::create( boost::shared_ptr< WModule > prototype ) 00104 { 00105 wlog::debug( "ModuleFactory" ) << "Creating new instance of prototype \"" << prototype->getName() << "\"."; 00106 00107 // for this a read lock is sufficient, gets unlocked if it looses scope 00108 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00109 00110 // ensure this one is a prototype and nothing else 00111 if( !checkPrototype( prototype, l ) ) 00112 { 00113 throw WPrototypeUnknown( std::string( "Could not clone module \"" + prototype->getName() + "\" since it is no prototype." ) ); 00114 } 00115 00116 // explicitly unlock 00117 l.reset(); 00118 00119 // call prototypes factory function 00120 boost::shared_ptr< WModule > clone = boost::shared_ptr< WModule >( prototype->factory() ); 00121 clone->setLocalPath( prototype->getLocalPath() ); // prototype and clone have the same local path. 00122 initializeModule( clone ); 00123 00124 return clone; 00125 } 00126 00127 void WModuleFactory::initializeModule( boost::shared_ptr< WModule > module ) 00128 { 00129 module->initialize(); 00130 } 00131 00132 boost::shared_ptr< WModuleFactory > WModuleFactory::getModuleFactory() 00133 { 00134 if( !m_instance ) 00135 { 00136 m_instance = boost::shared_ptr< WModuleFactory >( new WModuleFactory() ); 00137 } 00138 00139 return m_instance; 00140 } 00141 00142 00143 const boost::shared_ptr< WModule > WModuleFactory::isPrototypeAvailable( std::string name ) 00144 { 00145 // for this a read lock is sufficient, gets unlocked if it looses scope 00146 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00147 00148 // find first and only prototype (ensured during load()) 00149 boost::shared_ptr< WModule > ret = boost::shared_ptr< WModule >(); 00150 for( std::set< boost::shared_ptr< WModule > >::const_iterator listIter = l->get().begin(); listIter != l->get().end(); 00151 ++listIter ) 00152 { 00153 if( ( *listIter )->getName() == name ) 00154 { 00155 ret = ( *listIter ); 00156 break; 00157 } 00158 } 00159 00160 return ret; 00161 } 00162 00163 const boost::shared_ptr< WModule > WModuleFactory::getPrototypeByName( std::string name ) 00164 { 00165 boost::shared_ptr< WModule > ret = isPrototypeAvailable( name ); 00166 00167 // if not found -> throw 00168 if( ret == boost::shared_ptr< WModule >() ) 00169 { 00170 throw WPrototypeUnknown( std::string( "Could not find prototype \"" + name + "\"." ) ); 00171 } 00172 00173 return ret; 00174 } 00175 00176 const boost::shared_ptr< WModule > WModuleFactory::getPrototypeByInstance( boost::shared_ptr< WModule > instance ) 00177 { 00178 return getPrototypeByName( instance->getName() ); 00179 } 00180 00181 std::vector< WModule::ConstSPtr > WModuleFactory::getPrototypesByType( MODULE_TYPE type ) 00182 { 00183 std::vector< WModule::ConstSPtr > ret; 00184 00185 // for this a read lock is sufficient, gets unlocked if it looses scope 00186 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00187 00188 // find first and only prototype (ensured during load()) 00189 for( std::set< boost::shared_ptr< WModule > >::const_iterator listIter = l->get().begin(); listIter != l->get().end(); 00190 ++listIter ) 00191 { 00192 if( ( *listIter )->getType() == type ) 00193 { 00194 ret.push_back( *listIter ); 00195 } 00196 } 00197 00198 return ret; 00199 } 00200 00201 WModuleFactory::PrototypeSharedContainerType::ReadTicket WModuleFactory::getPrototypes() const 00202 { 00203 return m_prototypes.getReadTicket(); 00204 } 00205 00206 WCombinerTypes::WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost::shared_ptr< WModule > module ) 00207 { 00208 WCombinerTypes::WCompatiblesList compatibles; 00209 00210 // for this a read lock is sufficient, gets unlocked if it looses scope 00211 PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket(); 00212 00213 // First, add all modules with no input connector. 00214 for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end(); 00215 ++listIter ) 00216 { 00217 // get connectors of this prototype 00218 WModule::InputConnectorList pcons = ( *listIter )->getInputConnectors(); 00219 if( pcons.size() == 0 ) 00220 { 00221 // the modules which match every time need their own groups 00222 WCombinerTypes::WOneToOneCombiners lComp; 00223 00224 // 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 00225 lComp.push_back( boost::shared_ptr< WApplyCombiner >( new WApplyCombiner( module, "", *listIter, "" ) ) ); 00226 00227 // add this list 00228 compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) ); 00229 } 00230 } 00231 00232 // if NULL was specified, only return all modules without any inputs 00233 if( module ) 00234 { 00235 // go through every prototype 00236 for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end(); 00237 ++listIter ) 00238 { 00239 WCombinerTypes::WOneToOneCombiners lComp = WApplyCombiner::createCombinerList< WApplyCombiner >( module, ( *listIter ) ); 00240 00241 // add the group 00242 if( lComp.size() != 0 ) 00243 { 00244 compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) ); 00245 } 00246 } 00247 } 00248 00249 // unlock. No locking needed for further steps. 00250 l.reset(); 00251 00252 // sort the compatibles 00253 std::sort( compatibles.begin(), compatibles.end(), WCombinerTypes::compatiblesSort ); 00254 00255 return compatibles; 00256 }