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