OutPort.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00020 #ifndef OutPort_h
00021 #define OutPort_h
00022 
00023 #include <iostream>
00024 
00025 #include <coil/TimeValue.h>
00026 #include <coil/Time.h>
00027 #include <coil/TimeMeasure.h>
00028 #include <coil/OS.h>
00029 
00030 #include <rtm/RTC.h>
00031 #include <rtm/Typename.h>
00032 #include <rtm/OutPortBase.h>
00033 #include <rtm/CdrBufferBase.h>
00034 #include <rtm/PortCallBack.h>
00035 #include <rtm/OutPortConnector.h>
00036 
00037 namespace RTC
00038 {
00063   template <class DataType>
00064   class OutPort
00065     : public OutPortBase
00066   {
00067   public:
00091     OutPort(const char* name, DataType& value)
00092       : OutPortBase(name, toTypename<DataType>()), m_value(value),
00093         m_timeoutTick(1000), // timeout tick: 1ms
00094         m_readBlock(false), m_readTimeout(0),
00095         m_writeBlock(false), m_writeTimeout(0),
00096         m_OnWrite(NULL), m_OnWriteConvert(NULL),
00097         m_OnRead(NULL),  m_OnReadConvert(NULL),
00098         m_OnOverflow(NULL), m_OnUnderflow(NULL)
00099     {
00100     }
00101     
00117     virtual ~OutPort(void)
00118     {
00119     }
00120     
00162     virtual bool write(DataType& value)
00163     {
00164       if (m_OnWrite != NULL)
00165         {
00166           (*m_OnWrite)(value);
00167         }
00168 
00169       // check number of connectors
00170       size_t conn_size(m_connectors.size());
00171       if (!(conn_size > 0)) { return true; }
00172         
00173       // set timestamp
00174       coil::TimeValue tm(coil::gettimeofday());
00175       value.tm.sec  = tm.sec();
00176       value.tm.nsec = tm.usec() * 1000;
00177 
00178       // data -> (conversion) -> CDR stream
00179       m_cdr.rewindPtrs();
00180       if (m_OnWriteConvert != NULL)
00181         {
00182           ((*m_OnWriteConvert)(value)) >>= m_cdr;
00183         }
00184       else
00185         {
00186           value >>= m_cdr;
00187         }
00188 
00189       bool result(true);
00190       for (size_t i(0), len(conn_size); i < len; ++i)
00191         {
00192           ReturnCode ret;
00193           ret = m_connectors[i]->write(m_cdr);
00194           if (ret != PORT_OK)
00195             {
00196               result = false;
00197               if (ret == CONNECTION_LOST)
00198                 {
00199                   disconnect(m_connectors[i]->id());
00200                 }
00201             }
00202         }
00203       return result;
00204     }
00205     
00227     bool write()
00228     {
00229       return write(m_value);
00230     }
00231     
00257     bool operator<<(DataType& value)
00258     {
00259       return write(value);
00260     }
00261     
00309     bool read(DataType& value)
00310     {
00311       if (m_OnRead != NULL) (*m_OnRead)();      
00312       
00313 //      long int timeout = m_readTimeout;
00314       double timeout = (double)m_readTimeout / (double)TIMEVALUE_ONE_SECOND_IN_USECS;
00315       coil::TimeValue tm_cur, tm_pre;
00316       tm_pre = coil::gettimeofday();
00317       
00318       // blocking and timeout wait
00319       while (m_readBlock && this->isEmpty())
00320         {
00321           if (m_readTimeout < 0)
00322             {
00323               coil::usleep(m_timeoutTick);
00324               continue;
00325             }
00326           
00327           // timeout wait
00328           tm_cur = coil::gettimeofday();
00329           timeout -= (double)(tm_cur - tm_pre);
00330           if (timeout < 0) break;
00331           
00332           tm_pre = tm_cur;
00333           coil::usleep(m_timeoutTick);
00334         }
00335       
00336       if (this->isEmpty())
00337         {
00338           if (m_OnUnderflow != NULL)
00339             {
00340               value = (*m_OnUnderflow)();
00341               return false;
00342             }
00343           else
00344             {
00345               return false;
00346             }
00347         }
00348       
00349       if (m_OnReadConvert == NULL) 
00350         {
00351           value = this->get();
00352           return true;
00353         }
00354       else
00355         {
00356           value = (*m_OnReadConvert)(this->get());
00357           return true;
00358         }
00359       // never comes here
00360       return false;
00361     }
00362     
00386     void setReadBlock(bool block)
00387     {
00388       m_readBlock = block;
00389     }
00390     
00415     void setWriteBlock(bool block)
00416     {
00417       m_writeBlock = block;
00418     }
00419     
00443     void setReadTimeout(long int timeout)
00444     {
00445       m_readTimeout = timeout;
00446     }
00447     
00469     void setWriteTimeout(long int timeout)
00470     {
00471       m_writeTimeout = timeout;
00472     }
00473     
00493     inline void setOnWrite(OnWrite<DataType>* on_write)
00494     {
00495       m_OnWrite = on_write;
00496     }
00497     
00522     inline void setOnWriteConvert(OnWriteConvert<DataType>* on_wconvert)
00523     {
00524       m_OnWriteConvert = on_wconvert;
00525     }
00526     
00548     inline void setOnOverflow(OnOverflow<DataType>* on_overflow)
00549     {
00550       m_OnOverflow = on_overflow;
00551     }
00552     
00573     inline void setOnRead(OnRead<DataType>* on_read)
00574     {
00575       m_OnRead = on_read;
00576     }
00577     
00602     inline void setOnReadConvert(OnReadConvert<DataType>* on_rconvert)
00603     {
00604       m_OnReadConvert = on_rconvert;
00605     }
00606     
00628     inline void setOnUnderflow(OnUnderflow<DataType>* on_underflow)
00629     {
00630       m_OnUnderflow = on_underflow;
00631     }    
00632 
00633 
00634     inline void setOnConnect(OnConnect* on_connect)
00635     {
00636       m_OnConnect = on_connect;
00637     }
00638     
00639     inline void setOnDisconnect(OnConnect* on_disconnect)
00640     {
00641       m_OnDisconnect = on_disconnect;
00642     }
00643     
00644     virtual void onConnect(const char* id, PublisherBase* publisher)
00645     {
00646       std::cout << "onConnect(id = " << id << ")" << std::endl;
00647     }
00648 
00649     virtual void onDisconnect(const char* id)
00650     {
00651       std::cout << "onDisconnect(id = " << id << ")" << std::endl;
00652     }
00653 
00654 
00655 
00656     struct subscribe
00657     {
00658       subscribe(const ConnectorProfile& prof)
00659         : m_prof(&prof), _consumer(NULL) 
00660       {
00661       }
00662       
00663       subscribe(const subscribe& subs)
00664         : m_prof(subs.m_prof),
00665           _consumer(subs._consumer)
00666       {
00667       }
00668       
00669       subscribe& operator=(const subscribe& subs)
00670       {
00671         if (this == &subs) return *this;
00672         m_prof = subs.m_prof;
00673         _consumer = subs._consumer;
00674         return *this;
00675       }
00676       
00677       void operator()(InPortConsumer* cons)
00678       {
00679         if (cons->subscribeInterface(m_prof->properties))
00680           {
00681             _consumer = cons;
00682           }
00683       }
00684       const ConnectorProfile* m_prof;
00685       InPortConsumer* _consumer;
00686     };
00687 
00688 
00689   private:
00690     std::string m_typename;
00698     DataType& m_value;
00699     
00707     long int m_timeoutTick;
00708     
00716     bool m_readBlock;
00717     
00725     long int m_readTimeout;
00726     
00734     bool m_writeBlock;
00735     
00743     long int m_writeTimeout;
00744     
00752     OnWrite<DataType>* m_OnWrite;
00753     
00761     OnWriteConvert<DataType>* m_OnWriteConvert;
00762     
00770     OnRead<DataType>* m_OnRead;
00771     
00779     OnReadConvert<DataType>* m_OnReadConvert;
00780     
00788     OnOverflow<DataType>* m_OnOverflow;
00789     
00798     OnUnderflow<DataType>* m_OnUnderflow;
00799     
00800     OnConnect* m_OnConnect;
00801     OnDisconnect* m_OnDisconnect;
00802 
00803 
00804     std::vector<OutPortProvider*> m_providers;
00805     std::vector<InPortConsumer*> m_consumers;
00806     //    std::vector<ConnectorBase*> m_connectors;
00807     coil::TimeMeasure m_cdrtime;
00808     static const long int usec_per_sec = 1000000;
00809     cdrMemoryStream m_cdr;
00810   };
00811 }; // namespace RTC
00812 
00813 #endif // OutPort_h

Generated on Sun May 24 14:08:45 2009 for OpenRTM by  doxygen 1.5.3