source: finroc_plugins_runtime_construction/tPortCreationList.cpp @ 126:4dd615ab4b97

17.03
Last change on this file since 126:4dd615ab4b97 was 126:4dd615ab4b97, checked in by Max Reichardt <mreichardt@…>, 4 years ago

Removes clang compiler warnings

File size: 15.5 KB
Line 
1//
2// You received this file as part of Finroc
3// A framework for intelligent robot control
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    plugins/runtime_construction/tPortCreationList.cpp
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-12-02
27 *
28 */
29//----------------------------------------------------------------------
30#include "plugins/runtime_construction/tPortCreationList.h"
31
32//----------------------------------------------------------------------
33// External includes (system with <>, local with "")
34//----------------------------------------------------------------------
35#include <set>
36#include "rrlib/util/join.h"
37#include "core/port/tPortFactory.h"
38
39//----------------------------------------------------------------------
40// Internal includes with ""
41//----------------------------------------------------------------------
42#include "plugins/runtime_construction/tFinstructable.h"
43
44//----------------------------------------------------------------------
45// Debugging
46//----------------------------------------------------------------------
47#include <cassert>
48
49//----------------------------------------------------------------------
50// Namespace usage
51//----------------------------------------------------------------------
52
53//----------------------------------------------------------------------
54// Namespace declaration
55//----------------------------------------------------------------------
56namespace finroc
57{
58namespace runtime_construction
59{
60
61//----------------------------------------------------------------------
62// Forward declarations / typedefs / enums
63//----------------------------------------------------------------------
64typedef core::tFrameworkElement::tFlag tFlag;
65typedef core::tFrameworkElement::tFlags tFlags;
66
67//----------------------------------------------------------------------
68// Const values
69//----------------------------------------------------------------------
70
71//----------------------------------------------------------------------
72// Implementation
73//----------------------------------------------------------------------
74
75__attribute__((unused))
76static rrlib::rtti::tDataType<tPortCreationList> cTYPE;
77
78inline tPortCreateOptions ToPortCreateOptions(tFlags flags, tPortCreateOptions selectable_create_options)
79{
80  tPortCreateOptions result;
81  if (selectable_create_options.Get(tPortCreateOption::SHARED) && flags.Get(tFlag::SHARED))
82  {
83    result |= tPortCreateOption::SHARED;
84  }
85  if (selectable_create_options.Get(tPortCreateOption::OUTPUT) && flags.Get(tFlag::OUTPUT_PORT))
86  {
87    result |= tPortCreateOption::OUTPUT;
88  }
89  return result;
90}
91
92inline tFlags ToFlags(tPortCreateOptions create_options, tPortCreateOptions selectable_create_options)
93{
94  tFlags result;
95  if (selectable_create_options.Get(tPortCreateOption::SHARED) && create_options.Get(tPortCreateOption::SHARED))
96  {
97    result |= tFlag::SHARED;
98  }
99  if (selectable_create_options.Get(tPortCreateOption::OUTPUT) && create_options.Get(tPortCreateOption::OUTPUT))
100  {
101    result |= tFlag::OUTPUT_PORT;
102  }
103  return result;
104}
105
106
107tPortCreationList::tPortCreationList() :
108  selectable_create_options(),
109  list(),
110  io_vector(NULL),
111  flags(tFlags()),
112  ports_flagged_finstructed(true)
113{}
114
115tPortCreationList::tPortCreationList(core::tFrameworkElement& port_group, tFlags flags, const tPortCreateOptions& selectable_create_options, bool ports_flagged_finstructed) :
116  selectable_create_options(),
117  list(),
118  io_vector(&port_group),
119  flags(flags | (ports_flagged_finstructed ? tFlag::FINSTRUCTED : tFlag::PORT)),
120  ports_flagged_finstructed(ports_flagged_finstructed)
121{
122  if (!flags.Get(tFlag::SHARED) && selectable_create_options.Get(tPortCreateOption::SHARED))
123  {
124    this->selectable_create_options |= tPortCreateOption::SHARED;
125  }
126  if (!flags.Get(tFlag::OUTPUT_PORT) && selectable_create_options.Get(tPortCreateOption::OUTPUT))
127  {
128    this->selectable_create_options |= tPortCreateOption::OUTPUT;
129  }
130}
131
132void tPortCreationList::Add(const std::string& name, rrlib::rtti::tType dt, const tPortCreateOptions& create_options)
133{
134  rrlib::thread::tLock lock(io_vector->GetStructureMutex());
135  CheckPort(NULL, *io_vector, flags, name, dt, create_options, NULL);
136}
137
138void tPortCreationList::ApplyChanges(core::tFrameworkElement& io_vector_, tFlags flags_)
139{
140  rrlib::thread::tLock lock(io_vector->GetStructureMutex());
141  std::vector<core::tAbstractPort*> ports1;
142  GetPorts(*this->io_vector, ports1, ports_flagged_finstructed);
143  std::vector<core::tAbstractPort*> ports2;
144  GetPorts(io_vector_, ports2, ports_flagged_finstructed);
145
146  for (size_t i = 0u; i < ports1.size(); i++)
147  {
148    core::tAbstractPort* ap1 = ports1[i];
149    core::tAbstractPort* ap2 = i < ports2.size() ? ports2[i] : NULL;
150    CheckPort(ap2, io_vector_, flags_, ap1->GetName(), ap1->GetDataType(), ToPortCreateOptions(ap1->GetAllFlags(), selectable_create_options), ap1);
151  }
152  for (size_t i = ports1.size(); i < ports2.size(); i++)
153  {
154    ports2[i]->ManagedDelete();
155  }
156}
157
158void tPortCreationList::CheckPort(core::tAbstractPort* existing_port, core::tFrameworkElement& io_vector, tFlags flags,
159                                  const std::string& name, rrlib::rtti::tType type, const tPortCreateOptions& create_options, core::tAbstractPort* prototype)
160{
161  if (existing_port && existing_port->GetName() == name && existing_port->GetDataType() == type &&
162      existing_port->GetFlag(tFlag::VOLATILE) == flags.Get(tFlag::VOLATILE))
163  {
164    bool create_output_port = create_options.Get(tPortCreateOption::OUTPUT) || flags.Get(tFlag::OUTPUT_PORT);
165    bool create_shared_port = create_options.Get(tPortCreateOption::SHARED) || flags.Get(tFlag::SHARED);
166    if (((!selectable_create_options.Get(tPortCreateOption::OUTPUT)) || (existing_port->GetFlag(tFlag::OUTPUT_PORT) == create_output_port)) &&
167        ((!selectable_create_options.Get(tPortCreateOption::SHARED)) || (existing_port->GetFlag(tFlag::SHARED) == create_shared_port)))
168    {
169      // port is as it should be
170      return;
171    }
172  }
173  if (existing_port)
174  {
175    existing_port->ManagedDelete();
176  }
177
178  // compute flags to use
179  flags |= tFlag::ACCEPTS_DATA | tFlag::EMITS_DATA; // proxy port
180  flags |= ToFlags(create_options, selectable_create_options);
181  if (ports_flagged_finstructed)
182  {
183    flags |= tFlag::FINSTRUCTED;
184  }
185
186  FINROC_LOG_PRINT_TO(port_creation_list, DEBUG_VERBOSE_1, "Creating port ", name, " in IOVector ", io_vector);
187  core::tAbstractPort* created_port = core::tPortFactory::CreatePort(name, io_vector, type, flags);
188  if (created_port != NULL)
189  {
190    created_port->Init();
191  }
192//  if (ap != NULL && listener != NULL)
193//  {
194//    listener->PortCreated(ap, prototype);
195//  }
196}
197
198void tPortCreationList::GetPorts(const core::tFrameworkElement& elem, std::vector<core::tAbstractPort*>& result, bool finstructed_ports_only)
199{
200  result.clear();
201  for (auto it = elem.ChildPortsBegin(); it != elem.ChildPortsEnd(); ++it)
202  {
203    if ((!finstructed_ports_only) || it->GetFlag(tFlag::FINSTRUCTED))
204    {
205      result.push_back(&(*it));
206    }
207  }
208}
209
210int tPortCreationList::GetSize() const
211{
212  if (!io_vector)
213  {
214    return list.size();
215  }
216  int count = 0;
217  for (auto it = io_vector->ChildrenBegin(); it != io_vector->ChildrenEnd(); ++it)
218  {
219    count++;
220  }
221  return count;
222}
223
224void tPortCreationList::InitialSetup(core::tFrameworkElement& managed_io_vector, tFlags port_creation_flags, const tPortCreateOptions& selectable_create_options)
225{
226  assert((io_vector == NULL || io_vector == &managed_io_vector) && list.empty());
227  io_vector = &managed_io_vector;
228  flags = port_creation_flags;
229  this->selectable_create_options = selectable_create_options;
230}
231
232tPortCreationList::tEntry::tEntry(const std::string& name, const std::string& type, const tPortCreateOptions& create_options) :
233  name(name),
234  type(),
235  create_options(create_options)
236{
237  rrlib::serialization::tStringInputStream sis(type);
238  sis >> this->type;
239  assert(this->type.Get());
240}
241
242rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tPortCreationList& list)
243{
244  stream.WriteByte(list.selectable_create_options.Raw());
245  if (list.io_vector == NULL)
246  {
247    int size = list.list.size();
248    stream.WriteInt(size);
249    for (int i = 0; i < size; i++)
250    {
251      const tPortCreationList::tEntry& e = list.list[i];
252      stream.WriteString(e.name);
253      stream.WriteString(e.type.Get().GetName());
254      stream.WriteByte(e.create_options.Raw());
255    }
256  }
257  else
258  {
259    rrlib::thread::tLock lock(list.io_vector->GetStructureMutex());
260    std::vector<core::tAbstractPort*> ports;
261    list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed);
262    int size = ports.size();
263    stream.WriteInt(size);
264    for (int i = 0; i < size; i++)
265    {
266      core::tAbstractPort* p = ports[i];
267      stream.WriteString(p->GetName());
268      stream.WriteString(p->GetDataType().GetName());
269      stream.WriteByte(ToPortCreateOptions(p->GetAllFlags(), list.selectable_create_options).Raw());
270    }
271  }
272  return stream;
273}
274
275rrlib::serialization::tInputStream& operator >> (rrlib::serialization::tInputStream& stream, tPortCreationList& list)
276{
277  if (list.io_vector == NULL)
278  {
279    list.selectable_create_options = tPortCreateOptions(stream.ReadByte());
280    size_t size = stream.ReadInt();
281    list.list.clear();
282    for (size_t i = 0u; i < size; i++)
283    {
284      std::string name = stream.ReadString();
285      std::string type = stream.ReadString();
286      list.list.emplace_back(name, type, tPortCreateOptions(stream.ReadByte()));
287    }
288  }
289  else
290  {
291    rrlib::thread::tLock lock(list.io_vector->GetStructureMutex());
292    stream.ReadByte(); // skip selectable create options, as this is not defined by finstruct
293    size_t size = stream.ReadInt();
294    std::vector<core::tAbstractPort*> existing_ports;
295    list.GetPorts(*list.io_vector, existing_ports, list.ports_flagged_finstructed);
296    for (size_t i = 0u; i < size; i++)
297    {
298      std::string name = stream.ReadString();
299      std::string type_name = stream.ReadString();
300      rrlib::rtti::tType type = rrlib::rtti::tType::FindType(type_name);
301      if (!type)
302      {
303        FINROC_LOG_PRINT_STATIC(ERROR, "Error checking port from port creation deserialization: Type " + type_name + " not available");
304        throw std::runtime_error("Error checking port from port creation list deserialization: Type " + type_name + " not available");
305      }
306      tPortCreateOptions create_options(stream.ReadByte());
307
308      core::tAbstractPort* existing_port_with_this_name = NULL;
309      for (auto it = existing_ports.begin(); it != existing_ports.end(); ++it)
310      {
311        if ((*it)->GetName() == name)
312        {
313          existing_port_with_this_name = *it;
314          existing_ports.erase(it);
315          break;
316        }
317      }
318      list.CheckPort(existing_port_with_this_name, *list.io_vector, list.flags, name, type, create_options, NULL);
319    }
320
321    // delete any remaining ports
322    for (size_t i = 0; i < existing_ports.size(); i++)
323    {
324      existing_ports[i]->ManagedDelete();
325    }
326  }
327  return stream;
328}
329
330rrlib::xml::tNode& operator << (rrlib::xml::tNode& node, const tPortCreationList& list)
331{
332  if (!list.io_vector)
333  {
334    throw std::runtime_error("Only available on local systems");
335  }
336
337  rrlib::thread::tLock lock(list.io_vector->GetStructureMutex());
338  if (!list.ports_flagged_finstructed)
339  {
340    node.SetAttribute("showOutputSelection", list.selectable_create_options.Get(tPortCreateOption::OUTPUT));
341  }
342  std::vector<core::tAbstractPort*> ports;
343  list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed);
344  int size = ports.size();
345  for (int i = 0; i < size; i++)
346  {
347    core::tAbstractPort* p = ports[i];
348    rrlib::xml::tNode& child = node.AddChildNode("port");
349    child.SetAttribute("name", p->GetName());
350    child.SetAttribute("type", p->GetDataType().GetName());
351    tFinstructable::AddDependency(p->GetDataType());
352    if (list.selectable_create_options.Get(tPortCreateOption::OUTPUT))
353    {
354      child.SetAttribute("output", p->IsOutputPort());
355    }
356    if (list.selectable_create_options.Get(tPortCreateOption::SHARED) && p->GetFlag(tFlag::SHARED))
357    {
358      child.SetAttribute("shared", true);
359    }
360  }
361  return node;
362}
363
364const rrlib::xml::tNode& operator >> (const rrlib::xml::tNode& node, tPortCreationList& list)
365{
366  if (!list.io_vector)
367  {
368    throw std::runtime_error("Only available on local systems");
369  }
370
371  rrlib::thread::tLock lock(list.io_vector->GetStructureMutex());
372  if (!list.ports_flagged_finstructed)
373  {
374    list.selectable_create_options.Set(tPortCreateOption::OUTPUT, node.GetBoolAttribute("showOutputSelection"));
375  }
376  std::vector<core::tAbstractPort*> ports;
377  list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed);
378  size_t i = 0u;
379  std::set<std::string> missing_types;
380  for (rrlib::xml::tNode::const_iterator port = node.ChildrenBegin(); port != node.ChildrenEnd(); ++port, ++i)
381  {
382    core::tAbstractPort* ap = i < ports.size() ? ports[i] : NULL;
383    std::string port_name = port->Name();
384    assert(port_name.compare("port") == 0);
385    tPortCreateOptions create_options;
386    if (list.selectable_create_options.Get(tPortCreateOption::OUTPUT) && port->HasAttribute("output") && port->GetBoolAttribute("output"))
387    {
388      create_options |= tPortCreateOption::OUTPUT;
389    }
390    if (list.selectable_create_options.Get(tPortCreateOption::SHARED) && port->HasAttribute("shared") && port->GetBoolAttribute("shared"))
391    {
392      create_options |= tPortCreateOption::SHARED;
393    }
394    std::string dt_name = port->GetStringAttribute("type");
395    rrlib::rtti::tType dt = rrlib::rtti::tType::FindType(dt_name);
396    if (!dt)
397    {
398      missing_types.insert(dt_name);
399      continue;
400    }
401    if (dt.GetTypeClassification() == rrlib::rtti::tTypeClassification::RPC_TYPE && (!list.io_vector->GetFlag(core::tFrameworkElementFlag::INTERFACE_FOR_RPC_PORTS)))
402    {
403      FINROC_LOG_PRINT(WARNING, "Creating RPC port '", port->GetStringAttribute("name"), "' in non-RPC-port interface '", *list.io_vector, "'");
404    }
405    if (dt.GetTypeClassification() != rrlib::rtti::tTypeClassification::RPC_TYPE && (!list.io_vector->GetFlag(core::tFrameworkElementFlag::INTERFACE_FOR_DATA_PORTS)))
406    {
407      FINROC_LOG_PRINT(WARNING, "Creating data port '", port->GetStringAttribute("name"), "' in non-data-port interface '", *list.io_vector, "'");
408    }
409
410    list.CheckPort(ap, *list.io_vector, list.flags, port->GetStringAttribute("name"), dt, create_options, NULL);
411  }
412  for (; i < ports.size(); i++)
413  {
414    ports[i]->ManagedDelete();
415  }
416
417  if (missing_types.size())
418  {
419    std::string error_message = "Error creating ports in '" + list.io_vector->GetName() + "' because of missing types: " + rrlib::util::Join(missing_types, "; ");
420    FINROC_LOG_PRINT_STATIC(ERROR, error_message);
421    throw std::runtime_error(error_message);
422  }
423
424  return node;
425}
426
427//----------------------------------------------------------------------
428// End of namespace declaration
429//----------------------------------------------------------------------
430}
431}
Note: See TracBrowser for help on using the repository browser.