00001
00020 #ifndef OutPort_h
00021 #define OutPort_h
00022
00023 #include <rtm/BufferBase.h>
00024 #include <rtm/RingBuffer.h>
00025 #include <rtm/OutPortBase.h>
00026 #include <rtm/PortCallBack.h>
00027 #include <rtm/RTC.h>
00028 #include <iostream>
00029
00030 namespace RTC
00031 {
00056 template <class DataType,
00057 template <class DataType> class Buffer = RingBuffer >
00058 class OutPort
00059 : public OutPortBase,
00060 public Buffer<DataType>
00061 {
00062 public:
00086 OutPort(const char* name, DataType& value, long int length = 8)
00087 : OutPortBase(name), Buffer<DataType>(length),
00088 m_value(value),
00089 m_timeoutTick(1000),
00090 m_readBlock(false), m_readTimeout(0),
00091 m_writeBlock(false), m_writeTimeout(0),
00092 m_OnWrite(NULL), m_OnWriteConvert(NULL),
00093 m_OnRead(NULL), m_OnReadConvert(NULL),
00094 m_OnOverflow(NULL), m_OnUnderflow(NULL)
00095 {
00096 }
00097
00113 virtual ~OutPort()
00114 {
00115 }
00116
00158 virtual bool write(const DataType& value)
00159 {
00160 if (m_OnWrite != NULL)
00161 {
00162 (*m_OnWrite)(value);
00163 }
00164
00165 long int timeout = m_writeTimeout;
00166
00167 timeval tm_cur, tm_pre;
00168 ACE_Time_Value tt;
00169 tt = ACE_OS::gettimeofday();
00170 tm_pre = tt.operator timeval();
00171
00172
00173 long int count(0);
00174 while (m_writeBlock && this->isFull())
00175 {
00176 if (m_writeTimeout < 0)
00177 {
00178 usleep(m_timeoutTick);
00179 continue;
00180 }
00181
00182
00183 ACE_Time_Value tt;
00184 tt = ACE_OS::gettimeofday();
00185 tm_cur = tt.operator timeval();
00186 long int sec (tm_cur.tv_sec - tm_pre.tv_sec);
00187 long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00188
00189 timeout -= (sec * usec_per_sec + usec);
00190 if (timeout < 0) break;
00191
00192 tm_pre = tm_cur;
00193 usleep(m_timeoutTick);
00194 ++count;
00195 }
00196
00197 if (this->isFull())
00198 {
00199 if (m_OnOverflow != NULL)
00200 (*m_OnOverflow)(value);
00201 return false;
00202 }
00203
00204 if (m_OnWriteConvert == NULL)
00205 {
00206 this->put(value);
00207 }
00208 else
00209 {
00210 this->put((*m_OnWriteConvert)(value));
00211 }
00212 notify();
00213 return true;
00214 }
00215
00237 bool write()
00238 {
00239 return write(m_value);
00240 }
00241
00267 bool operator<<(DataType& value)
00268 {
00269 return write(value);
00270 }
00271
00319 bool read(DataType& value)
00320 {
00321 if (m_OnRead != NULL) (*m_OnRead)();
00322
00323 long int timeout = m_readTimeout;
00324 timeval tm_cur, tm_pre;
00325 ACE_Time_Value tt;
00326 tt = ACE_OS::gettimeofday();
00327 tm_pre = tt.operator timeval();
00328
00329
00330 while (m_readBlock && this->isEmpty())
00331 {
00332 if (m_readTimeout < 0)
00333 {
00334 usleep(m_timeoutTick);
00335 continue;
00336 }
00337
00338
00339 ACE_Time_Value tt;
00340 tt = ACE_OS::gettimeofday();
00341 tm_cur = tt.operator timeval();
00342 long int sec (tm_cur.tv_sec - tm_pre.tv_sec);
00343 long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00344
00345 timeout -= (sec * usec_per_sec + usec);
00346 if (timeout < 0) break;
00347
00348 tm_pre = tm_cur;
00349 usleep(m_timeoutTick);
00350 }
00351
00352 if (this->isEmpty())
00353 {
00354 if (m_OnUnderflow != NULL)
00355 {
00356 value = (*m_OnUnderflow)();
00357 return false;
00358 }
00359 else
00360 {
00361 return false;
00362 }
00363 }
00364
00365 if (m_OnReadConvert == NULL)
00366 {
00367 value = this->get();
00368 return true;
00369 }
00370 else
00371 {
00372 value = (*m_OnReadConvert)(this->get());
00373 return true;
00374 }
00375
00376 return false;
00377 }
00378
00402 void setReadBlock(bool block)
00403 {
00404 m_readBlock = block;
00405 }
00406
00431 void setWriteBlock(bool block)
00432 {
00433 m_writeBlock = block;
00434 }
00435
00459 void setReadTimeout(long int timeout)
00460 {
00461 m_readTimeout = timeout;
00462 }
00463
00485 void setWriteTimeout(long int timeout)
00486 {
00487 m_writeTimeout = timeout;
00488 }
00489
00509 inline void setOnWrite(OnWrite<DataType>* on_write)
00510 {
00511 m_OnWrite = on_write;
00512 }
00513
00538 inline void setOnWriteConvert(OnWriteConvert<DataType>* on_wconvert)
00539 {
00540 m_OnWriteConvert = on_wconvert;
00541 }
00542
00564 inline void setOnOverflow(OnOverflow<DataType>* on_overflow)
00565 {
00566 m_OnOverflow = on_overflow;
00567 }
00568
00589 inline void setOnRead(OnRead<DataType>* on_read)
00590 {
00591 m_OnRead = on_read;
00592 }
00593
00618 inline void setOnReadConvert(OnReadConvert<DataType>* on_rconvert)
00619 {
00620 m_OnReadConvert = on_rconvert;
00621 }
00622
00644 inline void setOnUnderflow(OnUnderflow<DataType>* on_underflow)
00645 {
00646 m_OnUnderflow = on_underflow;
00647 }
00648
00649 private:
00657 DataType& m_value;
00658
00666 long int m_timeoutTick;
00667
00675 bool m_readBlock;
00676
00684 long int m_readTimeout;
00685
00693 bool m_writeBlock;
00694
00702 long int m_writeTimeout;
00703
00711 OnWrite<DataType>* m_OnWrite;
00712
00720 OnWriteConvert<DataType>* m_OnWriteConvert;
00721
00729 OnRead<DataType>* m_OnRead;
00730
00738 OnReadConvert<DataType>* m_OnReadConvert;
00739
00747 OnOverflow<DataType>* m_OnOverflow;
00748
00757 OnUnderflow<DataType>* m_OnUnderflow;
00758
00759 static const long int usec_per_sec = 1000000;
00760 };
00761 };
00762
00763 #endif // OutPort_h