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
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
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
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
00197 while (m_readBlock && this->isEmpty())
00198 {
00199 if (m_readTimeout < 0)
00200 {
00201 usleep(m_timeoutTick);
00202 continue;
00203 }
00204
00205
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
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 };
00528
00529 #endif // OutPort_h