00001
00020 #ifndef OutPort_h
00021 #define OutPort_h
00022
00023 #include <iostream>
00024
00025 #include <coil/TimeValue.h>
00026 #include <coil/Time.h>
00027 #include <coil/TimeMeasure.h>
00028 #include <coil/OS.h>
00029
00030 #include <rtm/RTC.h>
00031 #include <rtm/Typename.h>
00032 #include <rtm/OutPortBase.h>
00033 #include <rtm/CdrBufferBase.h>
00034 #include <rtm/PortCallBack.h>
00035 #include <rtm/OutPortConnector.h>
00036
00037 namespace RTC
00038 {
00063 template <class DataType>
00064 class OutPort
00065 : public OutPortBase
00066 {
00067 public:
00091 OutPort(const char* name, DataType& value)
00092 : OutPortBase(name, toTypename<DataType>()), m_value(value),
00093 m_timeoutTick(1000),
00094 m_readBlock(false), m_readTimeout(0),
00095 m_writeBlock(false), m_writeTimeout(0),
00096 m_OnWrite(NULL), m_OnWriteConvert(NULL),
00097 m_OnRead(NULL), m_OnReadConvert(NULL),
00098 m_OnOverflow(NULL), m_OnUnderflow(NULL)
00099 {
00100 }
00101
00117 virtual ~OutPort(void)
00118 {
00119 }
00120
00162 virtual bool write(DataType& value)
00163 {
00164 if (m_OnWrite != NULL)
00165 {
00166 (*m_OnWrite)(value);
00167 }
00168
00169
00170 size_t conn_size(m_connectors.size());
00171 if (!(conn_size > 0)) { return true; }
00172
00173
00174 coil::TimeValue tm(coil::gettimeofday());
00175 value.tm.sec = tm.sec();
00176 value.tm.nsec = tm.usec() * 1000;
00177
00178
00179 m_cdr.rewindPtrs();
00180 if (m_OnWriteConvert != NULL)
00181 {
00182 ((*m_OnWriteConvert)(value)) >>= m_cdr;
00183 }
00184 else
00185 {
00186 value >>= m_cdr;
00187 }
00188
00189 bool result(true);
00190 for (size_t i(0), len(conn_size); i < len; ++i)
00191 {
00192 ReturnCode ret;
00193 ret = m_connectors[i]->write(m_cdr);
00194 if (ret != PORT_OK)
00195 {
00196 result = false;
00197 if (ret == CONNECTION_LOST)
00198 {
00199 disconnect(m_connectors[i]->id());
00200 }
00201 }
00202 }
00203 return result;
00204 }
00205
00227 bool write()
00228 {
00229 return write(m_value);
00230 }
00231
00257 bool operator<<(DataType& value)
00258 {
00259 return write(value);
00260 }
00261
00309 bool read(DataType& value)
00310 {
00311 if (m_OnRead != NULL) (*m_OnRead)();
00312
00313
00314 double timeout = (double)m_readTimeout / (double)TIMEVALUE_ONE_SECOND_IN_USECS;
00315 coil::TimeValue tm_cur, tm_pre;
00316 tm_pre = coil::gettimeofday();
00317
00318
00319 while (m_readBlock && this->isEmpty())
00320 {
00321 if (m_readTimeout < 0)
00322 {
00323 coil::usleep(m_timeoutTick);
00324 continue;
00325 }
00326
00327
00328 tm_cur = coil::gettimeofday();
00329 timeout -= (double)(tm_cur - tm_pre);
00330 if (timeout < 0) break;
00331
00332 tm_pre = tm_cur;
00333 coil::usleep(m_timeoutTick);
00334 }
00335
00336 if (this->isEmpty())
00337 {
00338 if (m_OnUnderflow != NULL)
00339 {
00340 value = (*m_OnUnderflow)();
00341 return false;
00342 }
00343 else
00344 {
00345 return false;
00346 }
00347 }
00348
00349 if (m_OnReadConvert == NULL)
00350 {
00351 value = this->get();
00352 return true;
00353 }
00354 else
00355 {
00356 value = (*m_OnReadConvert)(this->get());
00357 return true;
00358 }
00359
00360 return false;
00361 }
00362
00386 void setReadBlock(bool block)
00387 {
00388 m_readBlock = block;
00389 }
00390
00415 void setWriteBlock(bool block)
00416 {
00417 m_writeBlock = block;
00418 }
00419
00443 void setReadTimeout(long int timeout)
00444 {
00445 m_readTimeout = timeout;
00446 }
00447
00469 void setWriteTimeout(long int timeout)
00470 {
00471 m_writeTimeout = timeout;
00472 }
00473
00493 inline void setOnWrite(OnWrite<DataType>* on_write)
00494 {
00495 m_OnWrite = on_write;
00496 }
00497
00522 inline void setOnWriteConvert(OnWriteConvert<DataType>* on_wconvert)
00523 {
00524 m_OnWriteConvert = on_wconvert;
00525 }
00526
00548 inline void setOnOverflow(OnOverflow<DataType>* on_overflow)
00549 {
00550 m_OnOverflow = on_overflow;
00551 }
00552
00573 inline void setOnRead(OnRead<DataType>* on_read)
00574 {
00575 m_OnRead = on_read;
00576 }
00577
00602 inline void setOnReadConvert(OnReadConvert<DataType>* on_rconvert)
00603 {
00604 m_OnReadConvert = on_rconvert;
00605 }
00606
00628 inline void setOnUnderflow(OnUnderflow<DataType>* on_underflow)
00629 {
00630 m_OnUnderflow = on_underflow;
00631 }
00632
00633
00634 inline void setOnConnect(OnConnect* on_connect)
00635 {
00636 m_OnConnect = on_connect;
00637 }
00638
00639 inline void setOnDisconnect(OnConnect* on_disconnect)
00640 {
00641 m_OnDisconnect = on_disconnect;
00642 }
00643
00644 virtual void onConnect(const char* id, PublisherBase* publisher)
00645 {
00646 std::cout << "onConnect(id = " << id << ")" << std::endl;
00647 }
00648
00649 virtual void onDisconnect(const char* id)
00650 {
00651 std::cout << "onDisconnect(id = " << id << ")" << std::endl;
00652 }
00653
00654
00655
00656 struct subscribe
00657 {
00658 subscribe(const ConnectorProfile& prof)
00659 : m_prof(&prof), _consumer(NULL)
00660 {
00661 }
00662
00663 subscribe(const subscribe& subs)
00664 : m_prof(subs.m_prof),
00665 _consumer(subs._consumer)
00666 {
00667 }
00668
00669 subscribe& operator=(const subscribe& subs)
00670 {
00671 if (this == &subs) return *this;
00672 m_prof = subs.m_prof;
00673 _consumer = subs._consumer;
00674 return *this;
00675 }
00676
00677 void operator()(InPortConsumer* cons)
00678 {
00679 if (cons->subscribeInterface(m_prof->properties))
00680 {
00681 _consumer = cons;
00682 }
00683 }
00684 const ConnectorProfile* m_prof;
00685 InPortConsumer* _consumer;
00686 };
00687
00688
00689 private:
00690 std::string m_typename;
00698 DataType& m_value;
00699
00707 long int m_timeoutTick;
00708
00716 bool m_readBlock;
00717
00725 long int m_readTimeout;
00726
00734 bool m_writeBlock;
00735
00743 long int m_writeTimeout;
00744
00752 OnWrite<DataType>* m_OnWrite;
00753
00761 OnWriteConvert<DataType>* m_OnWriteConvert;
00762
00770 OnRead<DataType>* m_OnRead;
00771
00779 OnReadConvert<DataType>* m_OnReadConvert;
00780
00788 OnOverflow<DataType>* m_OnOverflow;
00789
00798 OnUnderflow<DataType>* m_OnUnderflow;
00799
00800 OnConnect* m_OnConnect;
00801 OnDisconnect* m_OnDisconnect;
00802
00803
00804 std::vector<OutPortProvider*> m_providers;
00805 std::vector<InPortConsumer*> m_consumers;
00806
00807 coil::TimeMeasure m_cdrtime;
00808 static const long int usec_per_sec = 1000000;
00809 cdrMemoryStream m_cdr;
00810 };
00811 };
00812
00813 #endif // OutPort_h