00001
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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),
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
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
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
00196 while (m_readBlock && this->isEmpty())
00197 {
00198 if (m_readTimeout < 0)
00199 {
00200 usleep(m_timeoutTick);
00201 continue;
00202 }
00203
00204
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
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 };
00527
00528 #endif // OutPort_h