Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

OutPort.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00020 /*
00021  * $Log: OutPort.h,v $
00022  * Revision 1.2.4.1  2007/07/20 15:58:03  n-ando
00023  * Now ACE_OS::gettimeofday() is used for win32 porting.
00024  *
00025  * Revision 1.2  2007/01/06 17:56:19  n-ando
00026  * A trivial fix.
00027  *
00028  * Revision 1.1  2006/12/02 18:45:30  n-ando
00029  * The first commitment.
00030  *
00031  *
00032  */
00033 
00034 #ifndef OutPort_h
00035 #define OutPort_h
00036  
00037 #include <rtm/BufferBase.h>
00038 #include <rtm/RingBuffer.h>
00039 #include <rtm/OutPortBase.h>
00040 #include <rtm/PortCallBack.h>
00041 #include <rtm/RTC.h>
00042 #include <iostream>
00043 
00044 namespace RTC
00045 {
00061   template <class DataType,
00062             template <class DataType> class Buffer = RingBuffer >
00063   class OutPort
00064     : public OutPortBase,
00065       public Buffer<DataType>
00066   {
00067   public:
00079     OutPort(const char* name, DataType& value, long int length = 8)
00080       : OutPortBase(name), Buffer<DataType>(length),
00081         m_value(value),
00082         m_timeoutTick(1000), // timeout tick: 1ms
00083         m_readBlock(false), m_readTimeout(0),
00084         m_writeBlock(false), m_writeTimeout(0),
00085         m_OnWrite(NULL), m_OnWriteConvert(NULL),
00086         m_OnRead(NULL),  m_OnReadConvert(NULL),
00087         m_OnOverflow(NULL), m_OnUnderflow(NULL)
00088     {
00089       
00090     }
00091     
00092     virtual ~OutPort()
00093     {
00094     }
00095 
00107     virtual bool write(const DataType& value)
00108     {
00109       if (m_OnWrite != NULL)
00110         {
00111           (*m_OnWrite)(value);
00112         }
00113       
00114       long int timeout = m_writeTimeout;
00115       
00116       timeval tm_cur, tm_pre;
00117       ACE_Time_Value tt;
00118       tt = ACE_OS::gettimeofday();
00119       tm_pre = tt.operator timeval();
00120       
00121       // blocking and timeout wait
00122       long int count(0);
00123       while (m_writeBlock && this->isFull())
00124         {
00125           if (m_writeTimeout < 0) 
00126             {
00127               usleep(m_timeoutTick);
00128               continue;
00129             }
00130           
00131           // timeout wait
00132           ACE_Time_Value tt;
00133           tt = ACE_OS::gettimeofday();
00134           tm_cur = tt.operator timeval();
00135           long int sec (tm_cur.tv_sec  - tm_pre.tv_sec);
00136           long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00137           
00138           timeout -= (sec * usec_per_sec + usec);
00139           if (timeout < 0) break;
00140           
00141           tm_pre = tm_cur;
00142           usleep(m_timeoutTick);
00143           ++count;
00144         }
00145       
00146       if (this->isFull())
00147         {
00148           if (m_OnOverflow != NULL)
00149             (*m_OnOverflow)(value);
00150           return false;
00151         }
00152       
00153       if (m_OnWriteConvert == NULL) 
00154         {
00155           this->put(value);
00156         }
00157       else
00158         {
00159           this->put((*m_OnWriteConvert)(value));
00160         }
00161       notify();
00162       return true;
00163     }
00164 
00165     bool write()
00166     {
00167       return write(m_value);
00168     }
00169 
00170     bool operator<<(DataType& value)
00171     {
00172       return write(value);
00173     }
00174 
00186     bool read(DataType& value)
00187     {
00188       if (m_OnRead != NULL) (*m_OnRead)();      
00189       
00190       long int timeout = m_readTimeout;
00191       timeval tm_cur, tm_pre;
00192       ACE_Time_Value tt;
00193       tt = ACE_OS::gettimeofday();
00194       tm_pre = tt.operator timeval();
00195 
00196       // blocking and timeout wait
00197       while (m_readBlock && this->isEmpty())
00198       {
00199           if (m_readTimeout < 0)
00200             {
00201               usleep(m_timeoutTick);
00202               continue;
00203             }
00204           
00205           // timeout wait
00206           ACE_Time_Value tt;
00207           tt = ACE_OS::gettimeofday();
00208           tm_cur = tt.operator timeval();
00209           long int sec (tm_cur.tv_sec  - tm_pre.tv_sec);
00210           long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00211           
00212           timeout -= (sec * usec_per_sec + usec);
00213           if (timeout < 0) break;
00214           
00215           tm_pre = tm_cur;
00216           usleep(m_timeoutTick);
00217         }
00218       
00219       if (this->isEmpty())
00220         {
00221           if (m_OnUnderflow != NULL)
00222             {
00223               value = (*m_OnUnderflow)();
00224               return false;
00225             }
00226           else
00227             {
00228               return false;
00229             }
00230         }
00231 
00232       if (m_OnReadConvert == NULL) 
00233         {
00234           value = this->get();
00235           return true;
00236         }
00237       else
00238         {
00239           value = (*m_OnReadConvert)(this->get());
00240           return true;
00241         }
00242       // never comes here
00243       return false;
00244     }
00245 
00257     void setReadBlock(bool block)
00258     {
00259       m_readBlock = block;
00260     }
00261 
00273     void setWriteBlock(bool block)
00274     {
00275       m_writeBlock = block;
00276     }
00277 
00293     void setReadTimeout(long int timeout)
00294     {
00295       m_readTimeout = timeout;
00296     }
00297 
00313     void setWriteTimeout(long int timeout)
00314     {
00315       m_writeTimeout = timeout;
00316     }
00317 
00329     inline void setOnWrite(OnWrite<DataType>* on_write)
00330     {
00331       m_OnWrite = on_write;
00332     }
00333 
00345     inline void setOnWriteConvert(OnWriteConvert<DataType>* on_wconvert)
00346     {
00347       m_OnWriteConvert = on_wconvert;
00348     }
00349 
00361     inline void setOnOverflow(OnOverflow<DataType>* on_overflow)
00362     {
00363       m_OnOverflow = on_overflow;
00364     }
00365 
00377     inline void setOnRead(OnRead<DataType>* on_read)
00378     {
00379       m_OnRead = on_read;
00380     }
00381 
00393     inline void setOnReadConvert(OnReadConvert<DataType>* on_rconvert)
00394     {
00395       m_OnReadConvert = on_rconvert;
00396     }
00397 
00409     inline void setOnUnderflow(OnUnderflow<DataType>* on_underflow)
00410     {
00411       m_OnUnderflow = on_underflow;
00412     }    
00413 
00414   private:
00422     DataType& m_value;
00423 
00431     long int m_timeoutTick;
00432 
00440     bool m_readBlock;
00441 
00449     long int m_readTimeout;
00450 
00458     bool m_writeBlock;
00459 
00467     long int m_writeTimeout;
00468 
00476     OnWrite<DataType>* m_OnWrite;
00477 
00485     OnWriteConvert<DataType>* m_OnWriteConvert;
00486 
00494     OnRead<DataType>* m_OnRead;
00495 
00503     OnReadConvert<DataType>* m_OnReadConvert;
00504 
00512     OnOverflow<DataType>* m_OnOverflow;
00513 
00522     OnUnderflow<DataType>* m_OnUnderflow;
00523 
00524     static const long int usec_per_sec = 1000000;
00525 
00526   };
00527 }; // namespace RTC
00528 
00529 #endif // OutPort_h

Generated on Fri Sep 21 12:03:45 2007 for OpenRTM by  doxygen 1.4.1