OpenWalnut 1.2.5

WModuleFactory.cpp

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 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends