source: finroc_plugins_network_transport/runtime_info/tFrameworkElementInfo.h @ 18:fd9f94b5d096

17.03
Last change on this file since 18:fd9f94b5d096 was 18:fd9f94b5d096, checked in by Max Reichardt <mreichardt@…>, 5 years ago

Refactors and greatly extends common functionality on runtime info classes (they used to be in 'structure_info' subdirectory). Runtime info serialization of diverse elements is now located in a common place - and fully based on the new register serialization mechanism from rrlib_serialization.

File size: 10.8 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/network_transport/runtime_info/tFrameworkElementInfo.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2013-01-12
27 *
28 * \brief   Contains tFrameworkElementInfo
29 *
30 * \b tFrameworkElementInfo
31 *
32 * Information on (shared) framework elements - as exchanged by peers.
33 *
34 */
35//----------------------------------------------------------------------
36#ifndef __plugins__network_transport__runtime_info__tFrameworkElementInfo_h__
37#define __plugins__network_transport__runtime_info__tFrameworkElementInfo_h__
38
39//----------------------------------------------------------------------
40// External includes (system with <>, local with "")
41//----------------------------------------------------------------------
42#include "plugins/data_ports/common/tAbstractDataPort.h"
43#include "plugins/data_ports/type_traits.h"
44#include "core/tFrameworkElementTags.h"
45#include "plugins/data_ports/common/tAbstractDataPort.h"
46
47//----------------------------------------------------------------------
48// Internal includes with ""
49//----------------------------------------------------------------------
50#include "plugins/network_transport/runtime_info/definitions.h"
51#include "plugins/network_transport/runtime_info/tRemoteType.h"
52
53//----------------------------------------------------------------------
54// Namespace declaration
55//----------------------------------------------------------------------
56namespace finroc
57{
58namespace network_transport
59{
60namespace runtime_info
61{
62
63//----------------------------------------------------------------------
64// Forward declarations / typedefs / enums
65//----------------------------------------------------------------------
66
67namespace internal
68{
69
70/*! Maximum number of links per port */
71enum { cMAX_LINKS = 3 };
72
73struct tLink
74{
75  /*! Path to this port (only required for shared ports) */
76  rrlib::uri::tPath path;
77
78  /*! Name of this framework element (from parent) */
79  std::string name;
80
81  /*! Handle of parent */
82  core::tFrameworkElement::tHandle parent_handle = 0;
83};
84
85typedef std::array<tLink, cMAX_LINKS> tLinkArray;
86
87void Serialize(rrlib::serialization::tOutputStream& stream, const core::tFrameworkElement::tFlags& flags, const tLinkArray& link_data,
88               const std::array<const std::string*, cMAX_LINKS>* alt_link_name_storage, uint8_t link_count, const rrlib::rtti::tType& type, const std::vector<std::string>& tags);
89}
90
91//----------------------------------------------------------------------
92// Class declaration
93//----------------------------------------------------------------------
94//! Framework element information
95/*!
96 * Information on (shared) framework elements - as exchanged by peers.
97 *
98 * In C++, this struct can only store info shared ports.
99 * The static Serialize method also serializes framework element info
100 * and port connection info.
101 */
102template <bool Tremote>
103struct tFrameworkElementInfo
104{
105  typedef typename core::tFrameworkElement::tHandle tHandle;
106  typedef typename core::tFrameworkElement::tFlag tFlag;
107  typedef typename core::tFrameworkElement::tFlags tFlags;
108  typedef typename std::conditional<Tremote, const tRemoteType*, rrlib::rtti::tType>::type tType;
109
110  struct tID
111  {
112    /*! Handle of element in runtime environment */
113    core::tFrameworkElement::tHandle handle = 0;
114
115    tID() : handle(0)
116    {}
117    tID(const core::tFrameworkElement& element) :
118      handle(element.GetHandle())
119    {}
120
121  } id;
122
123  struct tStaticInfo
124  {
125    /*! Framework element flags */
126    core::tFrameworkElement::tFlags flags;
127
128    typedef internal::tLinkArray tLinkArray;
129
130    /*! Per-link data - in fixed array for efficiency reasons */
131    tLinkArray link_data;
132
133    /*! Number of links */
134    uint8_t link_count;
135
136    /*! Type of port data */
137    tType type;
138
139    /*! Classification tags (strings) assigned to framework element */
140    std::vector<std::string> tags;
141
142
143    tStaticInfo() : link_count(0)
144    {}
145
146    template < bool ENABLE = !Tremote >
147    tStaticInfo(typename std::enable_if<ENABLE, const core::tFrameworkElement>::type& element) :
148      flags(element.GetAllFlags()),
149      link_count(0),
150      tags(core::tFrameworkElementTags::GetTags(element))
151    {
152      link_count = element.IsPort() ? element.GetLinkCount() : 1;
153      if (link_count > link_data.size())
154      {
155        FINROC_LOG_PRINT(WARNING, "Only three links are supported");
156        link_count = link_data.size();
157      }
158
159      bool shared_port = IsSharedPort(element);
160      for (size_t i = 0; i < link_count; i++)
161      {
162        if (shared_port)
163        {
164          element.GetPath(link_data[i].path, i);
165        }
166        link_data[i].name = element.GetLink(i).GetName();
167        link_data[i].parent_handle = element.GetParent(i)->GetHandle();
168      }
169
170      if (element.IsPort())
171      {
172        type = static_cast<const core::tAbstractPort&>(element).GetDataType();
173      }
174    }
175
176    template < bool ENABLE = !Tremote >
177    typename std::enable_if<ENABLE, bool>::type IsDataPort() const
178    {
179      return flags.Get(core::tFrameworkElementFlag::PORT) && data_ports::IsDataFlowType(type);
180    }
181
182  } static_info;
183
184  /*! Part of information that may be changed later */
185  struct tDynamicInfo
186  {
187    /*! Only relevant for ports: Strategy to use for port if it is destination port */
188    int16_t strategy;
189
190    tDynamicInfo() : strategy(-1)
191    {}
192    tDynamicInfo(const core::tFrameworkElement& element) :
193      strategy(-1)
194    {
195      if (IsDataPort(element))
196      {
197        strategy = static_cast<const data_ports::common::tAbstractDataPort&>(element).GetStrategy();
198      }
199    }
200
201  } dynamic_info;
202
203
204  tFrameworkElementInfo() : id(), static_info(), dynamic_info()
205  {}
206
207  template < bool ENABLE = !Tremote >
208  tFrameworkElementInfo(typename std::enable_if<ENABLE, const core::tFrameworkElement>::type& element) : id(element), static_info(element), dynamic_info(element)
209  {}
210
211  /*!
212   * \return Whether provided element is a data flow port
213   */
214  static bool IsDataPort(const core::tFrameworkElement& framework_element)
215  {
216    return framework_element.IsPort() && data_ports::IsDataFlowType(static_cast<const core::tAbstractPort&>(framework_element).GetDataType());
217  }
218
219  /*!
220   * \return Whether provided element a shared port (to be announced to other peers)?
221   */
222  static bool IsSharedPort(const core::tFrameworkElement& framework_element)
223  {
224    return framework_element.IsPort() && framework_element.GetFlag(core::tFrameworkElement::tFlag::SHARED) &&
225           (!framework_element.GetFlag(core::tFrameworkElement::tFlag::NETWORK_ELEMENT));
226  }
227
228  /*!
229   * Serializes info on single framework element to stream so that it can later
230   * be deserialized in typically another runtime environment.
231   *
232   * \param stream Binary stream to serialize to
233   * \param framework_element Framework element to serialize info of
234   *
235   * TODO: avoid frequent reallocation of (typically one) tPath
236   */
237  template < bool ENABLE = !Tremote >
238  static void Serialize(typename std::enable_if<ENABLE, rrlib::serialization::tOutputStream>::type& stream, const core::tFrameworkElement& framework_element)
239  {
240    rrlib::uri::tURI uri;
241
242    // collect links
243    internal::tLinkArray link_data;
244    std::array<const std::string*, internal::cMAX_LINKS> alt_link_name_storage;
245    size_t link_count = framework_element.GetLinkCount();
246    if (link_count > link_data.size())
247    {
248      FINROC_LOG_PRINT(WARNING, "Only three links are supported");
249      link_count = link_data.size();
250    }
251
252    tStaticInfo static_info;
253    bool shared_port = IsSharedPort(framework_element);
254    for (size_t i = 0; i < link_count; i++)
255    {
256      if (shared_port)
257      {
258        framework_element.GetPath(link_data[i].path, i);
259      }
260      alt_link_name_storage[i] = &framework_element.GetName();
261      link_data[i].parent_handle = framework_element.GetParent(i)->GetHandle();
262    }
263
264    // Serialize
265    stream << tID(framework_element);
266    internal::Serialize(stream, framework_element.GetAllFlags(), link_data, &alt_link_name_storage, link_count, framework_element.IsPort() ? static_cast<const core::tAbstractPort&>(framework_element).GetDataType() : rrlib::rtti::tType(), core::tFrameworkElementTags::GetTags(framework_element));
267    if (IsDataPort(framework_element))
268    {
269      stream << tDynamicInfo(framework_element);
270    }
271  }
272
273};
274
275typedef tFrameworkElementInfo<false> tLocalFrameworkElementInfo;
276typedef tFrameworkElementInfo<true> tRemoteFrameworkElementInfo;
277
278rrlib::serialization::tInputStream& operator >> (rrlib::serialization::tInputStream& stream, tRemoteFrameworkElementInfo& info);
279
280inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo::tID& info)
281{
282  stream << info.handle;
283  return stream;
284}
285
286inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo::tStaticInfo& info)
287{
288  internal::Serialize(stream, info.flags, info.link_data, nullptr, info.link_count, info.type, info.tags);
289  return stream;
290}
291
292inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo::tDynamicInfo& info)
293{
294  stream << info.strategy;
295  // As structure is only sent to client with new protocol, we can omit network update time
296  return stream;
297}
298
299inline rrlib::serialization::tInputStream& operator >> (rrlib::serialization::tInputStream& stream, tRemoteFrameworkElementInfo::tDynamicInfo& info)
300{
301  if (stream.GetSourceInfo().revision == 0)
302  {
303    stream.ReadInt();
304    stream >> info.strategy;
305    stream.ReadShort();
306  }
307  else
308  {
309    stream >> info.strategy;
310  }
311  return stream;
312}
313
314inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo& info)
315{
316  stream << info.id << info.static_info;
317  if (info.static_info.IsDataPort())
318  {
319    stream << info.dynamic_info;;
320  }
321  return stream;
322}
323
324
325//----------------------------------------------------------------------
326// End of namespace declaration
327//----------------------------------------------------------------------
328}
329}
330}
331
332#endif
Note: See TracBrowser for help on using the repository browser.