OpenWalnut  1.4.0
WModuleInputData.h
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 #ifndef WMODULEINPUTDATA_H
00026 #define WMODULEINPUTDATA_H
00027 
00028 #include <string>
00029 
00030 #include <boost/shared_ptr.hpp>
00031 #include <boost/thread/locks.hpp>
00032 
00033 // this is necessary since we have some kind of cyclic includes
00034 template < typename T > class WModuleOutputData;
00035 #include "WModuleOutputData.h"
00036 #include "exceptions/WModuleConnectorUnconnected.h"
00037 #include "../common/WTransferable.h"
00038 #include "../common/WPrototyped.h"
00039 
00040 #include "WModuleInputConnector.h"
00041 #include "WModuleOutputConnector.h"
00042 
00043 /**
00044  * Class offering an instantiate-able data connection between modules.
00045  * Due to is template style it is possible to bind nearly arbitrary data.
00046  */
00047 template < typename T >
00048 class WModuleInputData: public WModuleInputConnector
00049 {
00050 public:
00051     /**
00052      * Pointer to this. For convenience.
00053      */
00054     typedef boost::shared_ptr< WModuleInputData< T > > PtrType;
00055 
00056     /**
00057      * Pointer to this. For convenience.
00058      */
00059     typedef boost::shared_ptr< WModuleInputData< T > > SPtr;
00060 
00061     /**
00062      * Pointer to this. For convenience.
00063      */
00064     typedef boost::shared_ptr< const WModuleInputData< T > > ConstSPtr;
00065 
00066     /**
00067      * Reference to this type.
00068      */
00069     typedef WModuleInputData< T >& RefType;
00070 
00071     /**
00072      * Type of the connector.
00073      */
00074     typedef WModuleInputData< T > Type;
00075 
00076     /**
00077      * Typedef to the contained transferable.
00078      */
00079     typedef T TransferType;
00080 
00081     /**
00082      * Convenience method to create a new instance of this in data connector with proper type.
00083      *
00084      * \param module    the module owning this instance
00085      * \param name      the name of this connector.
00086      * \param description the description of this connector.
00087      *
00088      * \return the pointer to the created connector.
00089      */
00090     static PtrType create( boost::shared_ptr< WModule > module, std::string name = "", std::string description = "" );
00091 
00092     /**
00093      * Convenience method to create a new instance of this in data connector with proper type and add it to the list of connectors of the
00094      * specified module.
00095      *
00096      * \param module    the module owning this instance
00097      * \param name      the name of this connector.
00098      * \param description the description of this connector.
00099      *
00100      * \return the pointer to the created connector.
00101      */
00102     static PtrType createAndAdd( boost::shared_ptr< WModule > module, std::string name = "", std::string description = "" );
00103 
00104     /**
00105      * Constructor.
00106      *
00107      * \param module the module which is owner of this connector.
00108      * \param name The name of this connector.
00109      * \param description Short description of this connector.
00110      */
00111     WModuleInputData( boost::shared_ptr< WModule > module, std::string name = "", std::string description = "" ):
00112         WModuleInputConnector( module, name, description ),
00113         m_disconnecting( false )
00114     {
00115     };
00116 
00117     /**
00118      * Destructor.
00119      */
00120     virtual ~WModuleInputData()
00121     {
00122     };
00123 
00124     /**
00125      * Disconnects this connector if connected. If it is not connected: nothing happens.
00126      *
00127      * \param con the connector to disconnect.
00128      * \param removeFromOwnList if true the specified connection is also removed from the own connection list. If false it won't.
00129      */
00130     virtual void disconnect( boost::shared_ptr<WModuleConnector> con, bool removeFromOwnList = true );
00131 
00132     /**
00133      * Gives the currently set data and resets the update flag.
00134      *
00135      * \param reset reset the flag of updated() if true (default).
00136      *
00137      * \return the data currently set. NULL if no data has been sent yet or the connector is unconnected.
00138      */
00139     const boost::shared_ptr< T > getData( bool reset = true )
00140     {
00141         // get a lock
00142         boost::shared_lock<boost::shared_mutex> lock = boost::shared_lock<boost::shared_mutex>( m_connectionListLock );
00143 
00144         // Only reset change flag of requested
00145         if( reset )
00146         {
00147             handledUpdate();
00148         }
00149 
00150         // is there something in the list?
00151         if( m_disconnecting || m_connected.empty() )
00152         {
00153             lock.unlock();
00154             return boost::shared_ptr< T >();
00155         }
00156 
00157         // get data
00158         boost::shared_ptr< T > dat = boost::dynamic_pointer_cast< T >(
00159                 boost::dynamic_pointer_cast< WModuleOutputConnector >( *m_connected.begin() )->getRawData()
00160         );
00161 
00162         // unlock and return
00163         lock.unlock();
00164 
00165         return dat;
00166     };
00167 
00168     /**
00169      * Checks whether the specified connector is an input connector and compatible with T.
00170      *
00171      * \param con the connector to check against.
00172      *
00173      * \return true if compatible.
00174      */
00175     virtual bool connectable( boost::shared_ptr<WModuleConnector> con )
00176     {
00177         // NOTE: please consider the following: the input only accepts data which is of type T or higher. So only up casts from
00178         // con's type T2 to T are needed/allowed what ever
00179 
00180         if( !WModuleInputConnector::connectable( con ) )
00181         {
00182             return false;
00183         }
00184 
00185         // this calls virtual function to achieve the prototype of the WTransferable created with the type specified in
00186         // WOutputData< XYZ >
00187         boost::shared_ptr< WPrototyped > tProto =
00188             dynamic_cast< WModuleOutputConnector* >( con.get() )->getTransferPrototype(); // NOLINT
00189 
00190         // NOTE: Check the type of the transfered object and whether the connector is an output
00191         return dynamic_cast< T* >( tProto.get() ); // NOLINT
00192     };
00193 
00194 protected:
00195 private:
00196     /**
00197      * If true, the returned data will be NULL. Needed because disconnection process is based on multiple steps.
00198      */
00199     bool m_disconnecting;
00200 };
00201 
00202 template < typename T >
00203 void WModuleInputData< T >::disconnect( boost::shared_ptr<WModuleConnector> con, bool removeFromOwnList )
00204 {
00205     m_disconnecting = true;
00206     WModuleInputConnector::disconnect( con, removeFromOwnList );
00207     m_disconnecting = false;
00208 }
00209 
00210 template < typename T >
00211 typename WModuleInputData< T >::PtrType WModuleInputData< T >::create( boost::shared_ptr< WModule > module, std::string name,
00212                                                                                                             std::string description )
00213 {
00214     typedef typename WModuleInputData< T >::PtrType PTR;
00215     typedef typename WModuleInputData< T >::Type TYPE;
00216     return PTR( new TYPE( module, name, description ) );
00217 }
00218 
00219 template < typename T >
00220 typename WModuleInputData< T >::PtrType WModuleInputData< T >::createAndAdd( boost::shared_ptr< WModule > module, std::string name,
00221                                                                                                                   std::string description )
00222 {
00223     typename WModuleInputData< T >::PtrType c = create( module, name, description );
00224     module->addConnector( c );
00225     return c;
00226 }
00227 
00228 #endif  // WMODULEINPUTDATA_H
00229