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     virtual ~OutPort()
00092     {
00093     }
00094 
00106     virtual bool write(const DataType& value)
00107     {
00108       if (m_OnWrite != NULL)
00109         {
00110           (*m_OnWrite)(value);
00111         }
00112       
00113       long int timeout = m_writeTimeout;
00114       
00115       timeval tm_cur, tm_pre;
00116       ACE_Time_Value tt;
00117       tt = ACE_OS::gettimeofday();
00118       tm_pre = tt.operator timeval();
00119       
00120       // blocking and timeout wait
00121       long int count(0);
00122       while (m_writeBlock && this->isFull())
00123         {
00124           if (m_writeTimeout < 0) 
00125             {
00126               usleep(m_timeoutTick);
00127               continue;
00128             }
00129           
00130           // timeout wait
00131           ACE_Time_Value tt;
00132           tt = ACE_OS::gettimeofday();
00133           tm_cur = tt.operator timeval();
00134           long int sec (tm_cur.tv_sec  - tm_pre.tv_sec);
00135           long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00136           
00137           timeout -= (sec * usec_per_sec + usec);
00138           if (timeout < 0) break;
00139           
00140           tm_pre = tm_cur;
00141           usleep(m_timeoutTick);
00142           ++count;
00143         }
00144       
00145       if (this->isFull())
00146         {
00147           if (m_OnOverflow != NULL)
00148             (*m_OnOverflow)(value);
00149           return false;
00150         }
00151       
00152       if (m_OnWriteConvert == NULL) 
00153         {
00154           this->put(value);
00155         }
00156       else
00157         {
00158           this->put((*m_OnWriteConvert)(value));
00159         }
00160       notify();
00161       return true;
00162     }
00163 
00164     bool write()
00165     {
00166       return write(m_value);
00167     }
00168 
00169     bool operator<<(DataType& value)
00170     {
00171       return write(value);
00172     }
00173 
00185     bool read(DataType& value)
00186     {
00187       if (m_OnRead != NULL) (*m_OnRead)();      
00188       
00189       long int timeout = m_readTimeout;
00190       timeval tm_cur, tm_pre;
00191       ACE_Time_Value tt;
00192       tt = ACE_OS::gettimeofday();
00193       tm_pre = tt.operator timeval();
00194 
00195       // blocking and timeout wait
00196       while (m_readBlock && this->isEmpty())
00197       {
00198           if (m_readTimeout < 0)
00199             {
00200               usleep(m_timeoutTick);
00201               continue;
00202             }
00203           
00204           // timeout wait
00205           ACE_Time_Value tt;
00206           tt = ACE_OS::gettimeofday();
00207           tm_cur = tt.operator timeval();
00208           long int sec (tm_cur.tv_sec  - tm_pre.tv_sec);
00209           long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00210           
00211           timeout -= (sec * usec_per_sec + usec);
00212           if (timeout < 0) break;
00213           
00214           tm_pre = tm_cur;
00215           usleep(m_timeoutTick);
00216         }
00217       
00218       if (this->isEmpty())
00219         {
00220           if (m_OnUnderflow != NULL)
00221             {
00222               value = (*m_OnUnderflow)();
00223               return false;
00224             }
00225           else
00226             {
00227               return false;
00228             }
00229         }
00230 
00231       if (m_OnReadConvert == NULL) 
00232         {
00233           value = this->get();
00234           return true;
00235         }
00236       else
00237         {
00238           value = (*m_OnReadConvert)(this->get());
00239           return true;
00240         }
00241       // never comes here
00242       return false;
00243     }
00244 
00256     void setReadBlock(bool block)
00257     {
00258       m_readBlock = block;
00259     }
00260 
00272     void setWriteBlock(bool block)
00273     {
00274       m_writeBlock = block;
00275     }
00276 
00292     void setReadTimeout(long int timeout)
00293     {
00294       m_readTimeout = timeout;
00295     }
00296 
00312     void setWriteTimeout(long int timeout)
00313     {
00314       m_writeTimeout = timeout;
00315     }
00316 
00328     inline void setOnWrite(OnWrite<DataType>* on_write)
00329     {
00330       m_OnWrite = on_write;
00331     }
00332 
00344     inline void setOnWriteConvert(OnWriteConvert<DataType>* on_wconvert)
00345     {
00346       m_OnWriteConvert = on_wconvert;
00347     }
00348 
00360     inline void setOnOverflow(OnOverflow<DataType>* on_overflow)
00361     {
00362       m_OnOverflow = on_overflow;
00363     }
00364 
00376     inline void setOnRead(OnRead<DataType>* on_read)
00377     {
00378       m_OnRead = on_read;
00379     }
00380 
00392     inline void setOnReadConvert(OnReadConvert<DataType>* on_rconvert)
00393     {
00394       m_OnReadConvert = on_rconvert;
00395     }
00396 
00408     inline void setOnUnderflow(OnUnderflow<DataType>* on_underflow)
00409     {
00410       m_OnUnderflow = on_underflow;
00411     }    
00412 
00413   private:
00421     DataType& m_value;
00422 
00430     long int m_timeoutTick;
00431 
00439     bool m_readBlock;
00440 
00448     long int m_readTimeout;
00449 
00457     bool m_writeBlock;
00458 
00466     long int m_writeTimeout;
00467 
00475     OnWrite<DataType>* m_OnWrite;
00476 
00484     OnWriteConvert<DataType>* m_OnWriteConvert;
00485 
00493     OnRead<DataType>* m_OnRead;
00494 
00502     OnReadConvert<DataType>* m_OnReadConvert;
00503 
00511     OnOverflow<DataType>* m_OnOverflow;
00512 
00521     OnUnderflow<DataType>* m_OnUnderflow;
00522 
00523     static const long int usec_per_sec = 1000000;
00524 
00525   };
00526 }; // namespace RTC
00527 
00528 #endif // OutPort_h

Generated on Fri Oct 5 05:15:59 2007 for OpenRTM by  doxygen 1.4.1