00001
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef OutPort_h
00032 #define OutPort_h
00033
00034 #include <rtm/BufferBase.h>
00035 #include <rtm/RingBuffer.h>
00036 #include <rtm/OutPortBase.h>
00037 #include <rtm/PortCallBack.h>
00038 #include <iostream>
00039
00040 namespace RTC
00041 {
00057 template <class DataType,
00058 template <class DataType> class Buffer = RingBuffer >
00059 class OutPort
00060 : public OutPortBase,
00061 public Buffer<DataType>
00062 {
00063 public:
00075 OutPort(const char* name, DataType& value, long int length = 8)
00076 : OutPortBase(name), Buffer<DataType>(length),
00077 m_value(value),
00078 m_timeoutTick(1000),
00079 m_readBlock(false), m_readTimeout(0),
00080 m_writeBlock(false), m_writeTimeout(0),
00081 m_OnWrite(NULL), m_OnWriteConvert(NULL),
00082 m_OnRead(NULL), m_OnReadConvert(NULL),
00083 m_OnOverflow(NULL), m_OnUnderflow(NULL)
00084 {
00085 }
00086
00087 virtual ~OutPort()
00088 {
00089 }
00090
00102 virtual bool write(const DataType& value)
00103 {
00104 if (m_OnWrite != NULL)
00105 {
00106 (*m_OnWrite)(value);
00107 }
00108
00109 long int timeout = m_writeTimeout;
00110
00111 timeval tm_cur, tm_pre;
00112 gettimeofday(&tm_pre, NULL);
00113
00114
00115 long int count(0);
00116 while (m_writeBlock && this->isFull())
00117 {
00118 if (m_writeTimeout < 0)
00119 {
00120 usleep(m_timeoutTick);
00121 continue;
00122 }
00123
00124
00125 gettimeofday(&tm_cur, NULL);
00126 long int sec (tm_cur.tv_sec - tm_pre.tv_sec);
00127 long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00128
00129 timeout -= (sec * usec_per_sec + usec);
00130 if (timeout < 0) break;
00131
00132 tm_pre = tm_cur;
00133 usleep(m_timeoutTick);
00134 ++count;
00135 }
00136
00137 if (this->isFull())
00138 {
00139 if (m_OnOverflow != NULL)
00140 (*m_OnOverflow)(value);
00141 return false;
00142 }
00143
00144 if (m_OnWriteConvert == NULL)
00145 {
00146 this->put(value);
00147 }
00148 else
00149 {
00150 this->put((*m_OnWriteConvert)(value));
00151 }
00152 notify();
00153 return true;
00154 }
00155
00156 bool write()
00157 {
00158 return write(m_value);
00159 }
00160
00161 bool operator<<(DataType& value)
00162 {
00163 return write(value);
00164 }
00165
00177 bool read(DataType& value)
00178 {
00179 if (m_OnRead != NULL) (*m_OnRead)();
00180
00181 long int timeout = m_readTimeout;
00182
00183 timeval tm_cur, tm_pre;
00184 gettimeofday(&tm_pre, NULL);
00185
00186
00187 while (m_readBlock && this->isEmpty())
00188 {
00189 if (m_readTimeout < 0)
00190 {
00191 usleep(m_timeoutTick);
00192 continue;
00193 }
00194
00195
00196 gettimeofday(&tm_cur, NULL);
00197 long int sec (tm_cur.tv_sec - tm_pre.tv_sec);
00198 long int usec(tm_cur.tv_usec - tm_pre.tv_usec);
00199
00200 timeout -= (sec * usec_per_sec + usec);
00201 if (timeout < 0) break;
00202
00203 tm_pre = tm_cur;
00204 usleep(m_timeoutTick);
00205 }
00206
00207 if (this->isEmpty())
00208 {
00209 if (m_OnUnderflow != NULL)
00210 {
00211 value = (*m_OnUnderflow)();
00212 return false;
00213 }
00214 else
00215 {
00216 return false;
00217 }
00218 }
00219
00220 if (m_OnReadConvert == NULL)
00221 {
00222 value = this->get();
00223 return true;
00224 }
00225 else
00226 {
00227 value = (*m_OnReadConvert)(this->get());
00228 return true;
00229 }
00230
00231 return false;
00232 }
00233
00245 void setReadBlock(bool block)
00246 {
00247 m_readBlock = block;
00248 }
00249
00261 void setWriteBlock(bool block)
00262 {
00263 m_writeBlock = block;
00264 }
00265
00281 void setReadTimeout(long int timeout)
00282 {
00283 m_readTimeout = timeout;
00284 }
00285
00301 void setWriteTimeout(long int timeout)
00302 {
00303 m_writeTimeout = timeout;
00304 }
00305
00317 inline void setOnWrite(OnWrite<DataType>* on_write)
00318 {
00319 m_OnWrite = on_write;
00320 }
00321
00333 inline void setOnWriteConvert(OnWriteConvert<DataType>* on_wconvert)
00334 {
00335 m_OnWriteConvert = on_wconvert;
00336 }
00337
00349 inline void setOnOverflow(OnOverflow<DataType>* on_overflow)
00350 {
00351 m_OnOverflow = on_overflow;
00352 }
00353
00365 inline void setOnRead(OnRead<DataType>* on_read)
00366 {
00367 m_OnRead = on_read;
00368 }
00369
00381 inline void setOnReadConvert(OnReadConvert<DataType>* on_rconvert)
00382 {
00383 m_OnReadConvert = on_rconvert;
00384 }
00385
00397 inline void setOnUnderflow(OnUnderflow<DataType>* on_underflow)
00398 {
00399 m_OnUnderflow = on_underflow;
00400 }
00401
00402 private:
00410 DataType& m_value;
00411
00419 long int m_timeoutTick;
00420
00428 bool m_readBlock;
00429
00437 long int m_readTimeout;
00438
00446 bool m_writeBlock;
00447
00455 long int m_writeTimeout;
00456
00464 OnWrite<DataType>* m_OnWrite;
00465
00473 OnWriteConvert<DataType>* m_OnWriteConvert;
00474
00482 OnRead<DataType>* m_OnRead;
00483
00491 OnReadConvert<DataType>* m_OnReadConvert;
00492
00500 OnOverflow<DataType>* m_OnOverflow;
00501
00510 OnUnderflow<DataType>* m_OnUnderflow;
00511
00512 static const long int usec_per_sec = 1000000;
00513
00514 };
00515 };
00516
00517 #endif // OutPort_h