Orocos Real-Time Toolkit  2.9.0
OutputPort.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Thu Oct 22 11:59:08 CEST 2009 OutputPort.hpp
3 
4  OutputPort.hpp - description
5  -------------------
6  begin : Thu October 22 2009
7  copyright : (C) 2009 Sylvain Joyeux
8  email : sylvain.joyeux@m4x.org
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #ifndef ORO_OUTPUT_PORT_HPP
40 #define ORO_OUTPUT_PORT_HPP
41 
43 #include "base/DataObject.hpp"
45 #include "internal/Channels.hpp"
46 #include "internal/ConnFactory.hpp"
47 #include "Service.hpp"
48 #include "OperationCaller.hpp"
49 
50 #include "InputPort.hpp"
51 
52 namespace RTT
53 {
69  template<typename T>
71  {
72  private:
73  friend class internal::ConnInputEndpoint<T>;
75 
76  virtual bool connectionAdded( base::ChannelElementBase::shared_ptr channel_input, ConnPolicy const& policy ) {
77  // Initialize the new channel with last written data if requested
78  // (and available)
79 
80  // This this the input channel element of the whole connection
81  typename base::ChannelElement<T>::shared_ptr channel_el_input = channel_input.get()->narrow<T>();
82 
83  if (has_initial_sample)
84  {
85  T const& initial_sample = sample->Get();
86  if ( channel_el_input->data_sample(initial_sample, /* reset = */ false) != NotConnected ) {
87  if ( has_last_written_value && policy.init )
88  return ( channel_el_input->write(initial_sample) != NotConnected );
89  return true;
90  } else {
91  Logger::In in("OutputPort");
92  log(Error) << "Failed to pass data sample to data channel. Aborting connection."<<endlog();
93  return false;
94  }
95  }
96 
97  // even if we're not written, test the connection with a default sample.
98  return ( channel_el_input->data_sample( T(), /* reset = */ false ) != NotConnected );
99  }
100 
102  bool has_last_written_value;
104  // data_sample or by calling write() with keeps_next_written_value or
105  // keeps_last_written_value to true
106  bool has_initial_sample;
108  // This is used to initialize connections with a known sample
109  bool keeps_next_written_value;
111  // This is used to allow the use of the 'init' connection policy option
112  bool keeps_last_written_value;
114 
121  OutputPort( OutputPort const& orig );
122  OutputPort& operator=(OutputPort const& orig);
123 
124  public:
141  OutputPort(std::string const& name = "unnamed", bool keep_last_written_value = true)
142  : base::OutputPortInterface(name)
143  , endpoint(new internal::ConnInputEndpoint<T>(this))
144  , has_last_written_value(false)
145  , has_initial_sample(false)
146  , keeps_next_written_value(false)
147  , keeps_last_written_value(false)
148  , sample( new base::DataObject<T>() )
149  {
150  if (keep_last_written_value)
151  keepLastWrittenValue(true);
152  }
153 
154  virtual ~OutputPort() { disconnect(); }
155 
156  void keepNextWrittenValue(bool keep)
157  {
158  keeps_next_written_value = keep;
159  }
160 
161  void keepLastWrittenValue(bool keep)
162  {
163  keeps_last_written_value = keep;
164  }
165 
166  bool keepsLastWrittenValue() const { return keeps_last_written_value; }
167 
174  {
175  return sample->Get();
176  }
177 
184  bool getLastWrittenValue(T& sample) const
185  {
186  if (has_last_written_value)
187  {
188  this->sample->Get(sample);
189  return true;
190  }
191  return false;
192  }
193 
195  {
196  // we create this on the fly.
197  return new internal::DataObjectDataSource<T>( sample );
198  }
199 
209  void setDataSample(const T& sample)
210  {
211  this->sample->Set(sample);
212  has_initial_sample = true;
213  has_last_written_value = false;
214 
215  if (connected()) {
216  WriteStatus result = getEndpoint()->getWriteEndpoint()->data_sample(sample, /* reset = */ true);
217  if (result == NotConnected) {
218  log(Error) << "A channel of port " << getName() << " has been invalidated during setDataSample(), it will be removed" << endlog();
219  }
220  }
221  }
222 
227  void clear()
228  {
229  has_last_written_value = false;
230  getEndpoint()->getWriteEndpoint()->clear(); // only affects shared pull connections, where getInputEndpoint() would return the port's buffer object
231 
232  // eventually clear shared connection
234  if (shared_connection) {
235  shared_connection->clear();
236  }
237  }
238 
243  WriteStatus write(const T& sample)
244  {
245  if (keeps_last_written_value || keeps_next_written_value)
246  {
247  keeps_next_written_value = false;
248  has_initial_sample = true;
249  this->sample->Set(sample);
250  }
251  has_last_written_value = keeps_last_written_value;
252 
253  WriteStatus result = NotConnected;
254  if (connected()) {
255  result = getEndpoint()->getWriteEndpoint()->write(sample);
256  if (result == NotConnected) {
257  log(Error) << "A channel of port " << getName() << " has been invalidated during write(), it will be removed" << endlog();
258  }
259  }
260 
261  return result;
262  }
263 
265  {
267  boost::dynamic_pointer_cast< internal::AssignableDataSource<T> >(source);
268  if (ds)
269  return write(ds->rvalue());
270  else
271  {
273  boost::dynamic_pointer_cast< internal::DataSource<T> >(source);
274  if (ds)
275  return write(ds->get());
276  else
277  log(Error) << "trying to write from an incompatible data source" << endlog();
278  }
279  return WriteFailure;
280  }
281 
283  virtual const types::TypeInfo* getTypeInfo() const
285 
289  virtual base::PortInterface* clone() const
290  { return new OutputPort<T>(this->getName()); }
291 
298  { return new InputPort<T>(this->getName()); }
299 
301 
304  virtual bool createConnection(base::InputPortInterface& input_port, ConnPolicy const& policy)
305  {
306  return internal::ConnFactory::createConnection(*this, input_port, policy);
307  }
308 
309  virtual bool createStream(ConnPolicy const& policy)
310  {
311  return internal::ConnFactory::createStream(*this, policy);
312  }
313 
314 #ifndef ORO_DISABLE_PORT_DATA_SCRIPTING
315 
320  {
322  // Force resolution on the overloaded write method
323  typedef WriteStatus (OutputPort<T>::*WriteSample)(T const&);
324  WriteSample write_m = &OutputPort::write;
325  typedef T (OutputPort<T>::*LastSample)() const;
326  LastSample last_m = &OutputPort::getLastWrittenValue;
327  object->addSynchronousOperation("write", write_m, this).doc("Writes a sample on the port.").arg("sample", "");
328  object->addSynchronousOperation("last", last_m, this).doc("Returns last written value to this port.");
329  return object;
330  }
331 #endif
332 
334  {
335  assert(endpoint);
336  return endpoint.get();
337  }
338 
340  {
341  return getEndpoint()->getSharedBuffer();
342  }
343  };
344 
345 }
346 
347 #endif
348 
void setDataSample(const T &sample)
Provides this port a data sample that is representative for the samples being used in write()...
Definition: OutputPort.hpp:209
DataSource is a base class representing a generic way to read data of type T.
Definition: DataSource.hpp:94
The base class of the InputPort.
boost::intrusive_ptr< ChannelElement< T > > shared_ptr
virtual result_t get() const =0
Return the data as type T.
This is a channel element that represents the input endpoint of a connection, i.e.
boost::intrusive_ptr< SharedConnectionBase > shared_ptr
WriteStatus write(base::DataSourceBase::shared_ptr source)
Write this port using the value stored in source.
Definition: OutputPort.hpp:264
boost::shared_ptr< DataObjectInterface< T > > shared_ptr
Used for shared_ptr management.
boost::intrusive_ptr< ConnInputEndpoint< T > > shared_ptr
void clear()
Clears the last written value and all data stored in shared connection buffers.
Definition: OutputPort.hpp:227
OutputPort(std::string const &name="unnamed", bool keep_last_written_value=true)
Creates a named Output port.
Definition: OutputPort.hpp:141
virtual const types::TypeInfo * getTypeInfo() const
Returns the types::TypeInfo object for the port&#39;s type.
Definition: OutputPort.hpp:283
bool getLastWrittenValue(T &sample) const
Reads the last written value written to this port, in case it is kept by this port, otherwise, returns false.
Definition: OutputPort.hpp:184
void keepLastWrittenValue(bool keep)
Change the setting for keeping the last written value.
Definition: OutputPort.hpp:161
virtual FlowStatus Get(reference_t pull, bool copy_old_data=true) const =0
Get a copy of the Data of this data object.
const std::string & getName() const
Get the name of this Port.
virtual base::PortInterface * clone() const
Create a clone of this port with the same name.
Definition: OutputPort.hpp:289
A component&#39;s data input port.
Definition: InputPort.hpp:63
virtual internal::ConnInputEndpoint< T > * getEndpoint() const
Returns the input or output endpoint of this port (if any).
Definition: OutputPort.hpp:333
A connection policy object describes how a given connection should behave.
Definition: ConnPolicy.hpp:107
The base class of each OutputPort.
We can&#39;t use typedefs since C++ doesn&#39;t allow it for templated classes without specifying all the tem...
virtual Service * createPortObject()
Create accessor Object for this Port, for addition to a TaskContext Object interface.
Definition: OutputPort.hpp:319
This class allows storage and retrieval of operations, ports, attributes and properties provided by a...
Definition: Service.hpp:93
static ChannelElement< T > * narrow(ChannelElementBase *e)
Return a pointer to the typed instance of a ChannelElementBase.
static const types::TypeInfo * getTypeInfo()
Return the typeinfo object.
virtual Service * createPortObject()
Create accessor Object for this Port, for addition to a TaskContext Object interface.
virtual const_reference_t rvalue() const =0
Get a const reference to the value of this DataSource.
virtual bool createStream(ConnPolicy const &policy)
Creates a data stream from or to this port using connection-less transports.
Definition: OutputPort.hpp:309
static bool createStream(OutputPort< T > &output_port, ConnPolicy const &policy)
Creates, attaches and checks an outbound stream to an Output port.
bool createConnection(InputPortInterface &sink)
Connects this write port to the given read port, using as policy the default policy of the sink port...
A class for representing a user type, and which can build instances of that type. ...
Definition: TypeInfo.hpp:67
bool keepsLastWrittenValue() const
Returns true if this port records the last written value.
Definition: OutputPort.hpp:166
WriteStatus write(const T &sample)
Writes a new sample to all receivers (if any).
Definition: OutputPort.hpp:243
virtual bool connected() const
Returns true if there is at least one channel registered in this port&#39;s list of outputs.
boost::intrusive_ptr< ChannelElementBase > shared_ptr
boost::intrusive_ptr< DataSource< T > > shared_ptr
Definition: DataSource.hpp:115
boost::intrusive_ptr< AssignableDataSource< T > > shared_ptr
Use this type to store a pointer to an AssignableDataSource.
Definition: DataSource.hpp:198
bool init
If true, one should initialize the connection&#39;s value with the last value written on the writer port...
Definition: ConnPolicy.hpp:203
This object represents the default thread-safe data object implementation used by Orocos objects...
Definition: DataObject.hpp:65
virtual base::ChannelElement< T >::shared_ptr getSharedBuffer() const
Definition: OutputPort.hpp:339
A DataSource which has set() methods.
Definition: DataSource.hpp:184
Notify the Logger in which &#39;module&#39; the message occured.
Definition: Logger.hpp:159
virtual ~OutputPort()
Definition: OutputPort.hpp:154
void keepNextWrittenValue(bool keep)
Definition: OutputPort.hpp:156
internal::ConnectionManager cmanager
virtual void disconnect()
Removes any connection that either go to or come from this port.
A component&#39;s data output port.
Definition: OutputPort.hpp:70
virtual WriteStatus data_sample(param_t sample, bool reset=true)
Provides a data sample to initialize this connection.
boost::intrusive_ptr< DataSourceBase > shared_ptr
Use this type to store a pointer to a DataSourceBase.
virtual WriteStatus write(param_t sample)
Writes a new sample on this connection.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
The base class of every data flow port.
T getLastWrittenValue() const
Returns the last written value written to this port, in case it is kept by this port, otherwise, returns a default T().
Definition: OutputPort.hpp:173
virtual base::DataSourceBase::shared_ptr getDataSource() const
Returns a Data source that stores the last written value, or a null pointer if this port does not kee...
Definition: OutputPort.hpp:194
static bool createConnection(OutputPort< T > &output_port, base::InputPortInterface &input_port, ConnPolicy const &policy)
Creates a connection from a local output_port to a local or remote input_port.
A DataSource which is used to read a DataObject.
virtual base::PortInterface * antiClone() const
Create the anti-clone (inverse port) of this port with the same name A port for reading will return a...
Definition: OutputPort.hpp:297
WriteStatus
Returns the status of a data flow write operation.
Definition: FlowStatus.hpp:66
virtual bool createConnection(base::InputPortInterface &input_port, ConnPolicy const &policy)
Connects this write port to the given read port, using the given policy.
Definition: OutputPort.hpp:304
internal::SharedConnectionBase::shared_ptr getSharedConnection() const
Returns a pointer to the shared connection element this port may be connected to. ...