Changeset 134:4bc25c8cea06 in finroc_plugins_runtime_construction


Ignore:
Timestamp:
27.04.2020 05:59:58 (12 months ago)
Author:
Max Reichardt <mreichardt@…>
Branch:
17.03
Children:
135:c8f6a95b501e, 136:f79534c8ea55
Phase:
public
Message:

Adds 'include' mechanism to structure xml files. Tracks info on origins of created elements for this purpose (implementation allows to cleanly remove includes at runtime - and always preserves order of elements).

Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • tEditableInterfaces.cpp

    r126 r134  
    114114} 
    115115 
    116 core::tPortGroup& tEditableInterfaces::LoadInterfacePorts(const rrlib::xml::tNode& node) 
     116core::tPortGroup& tEditableInterfaces::LoadInterfacePorts(const rrlib::xml::tNode& node, bool mark_created_ports_finstructed, const tOrigin* origin) 
    117117{ 
    118118  std::string name = node.GetStringAttribute("name"); 
     
    121121    if (name == interface.first->GetName()) 
    122122    { 
    123       tPortCreationList port_creation_list(*interface.first, interface.first->GetDefaultPortFlags(), interface.second); 
     123      tPortCreationList port_creation_list(*interface.first, interface.first->GetDefaultPortFlags(), interface.second, mark_created_ports_finstructed, origin); 
    124124      node >> port_creation_list; 
    125125      return *interface.first; 
  • tEditableInterfaces.h

    r109 r134  
    8686public: 
    8787 
     88  typedef tPortCreationList::tOrigin tOrigin; 
     89 
    8890  /*! Listener notified whenever editable interfaces are changed */ 
    8991  class tListener 
     
    115117   * 
    116118   * \param node XML node to load ports from 
     119   * \param mark_created_ports_finstructed Whether to flag created ports as 'finstructed'. Only such ports are saved to XML file - and show up in interface editing dialog in finstruct. 
     120   * \param origin Origin for which to create and manage ports (all ports that do no match origin are not touched) 
    117121   * \return Interface whose ports were updated 
    118122   * 
    119123   * \throw Throws different kinds of std::exceptions if loading fails 
    120124   */ 
    121   core::tPortGroup& LoadInterfacePorts(const rrlib::xml::tNode& node); 
     125  core::tPortGroup& LoadInterfacePorts(const rrlib::xml::tNode& node, bool mark_created_ports_finstructed = true, const tOrigin* origin = nullptr); 
    122126 
    123127  /*! 
  • tFinstructable.cpp

    r132 r134  
    4545#include "plugins/runtime_construction/tEditableInterfaces.h" 
    4646#include "plugins/runtime_construction/dynamic_loading.h" 
     47#include "plugins/runtime_construction/tConstructorCreateModuleAction.h" 
    4748 
    4849//---------------------------------------------------------------------- 
     
    7374//---------------------------------------------------------------------- 
    7475 
     76namespace 
     77{ 
     78 
     79/*! We do not want to have this prefix in XML file names, as this will not be found when a system installation is used */ 
     80const char* cUNWANTED_XML_FILE_PREFIX = "sources/cpp/"; 
     81 
     82/*! Characters that are not escaped in path URIs */ 
     83const char* cUNENCODED_RESERVED_CHARACTERS_PATH = "!$&'()*+,;= @"; 
     84 
     85/*! Current version of file format (YYMM) */ 
     86const uint cVERSION = 1703; 
     87 
    7588//---------------------------------------------------------------------- 
    7689// Implementation 
     
    7891 
    7992/*! Thread currently saving finstructable group */ 
    80 static rrlib::thread::tThread* saving_thread = nullptr; 
     93rrlib::thread::tThread* saving_thread = nullptr; 
    8194 
    8295/*! Temporary variable for saving: .so files that should be loaded prior to instantiating this group */ 
    83 static std::set<tSharedLibrary> dependencies_tmp; 
     96std::set<tSharedLibrary> dependencies_tmp; 
    8497 
    8598/*! Loaded finroc libraries at startup */ 
    86 static std::set<tSharedLibrary> startup_loaded_finroc_libs; 
    87  
    88 /*! We do not want to have this prefix in XML file names, as this will not be found when a system installation is used */ 
    89 static const char* cUNWANTED_XML_FILE_PREFIX = "sources/cpp/"; 
    90  
    91 /*! Characters that are not escaped in path URIs */ 
    92 static const char* cUNENCODED_RESERVED_CHARACTERS_PATH = "!$&'()*+,;= @"; 
    93  
    94 /*! Current version of file format (YYMM) */ 
    95 static const uint cVERSION = 1703; 
    96  
    97 static rrlib::uri::tPath ReplaceInterfaceInPath(const rrlib::uri::tPath& path, const std::string& new_interface) 
     99std::set<tSharedLibrary> startup_loaded_finroc_libs; 
     100 
     101 
     102rrlib::uri::tPath ReplaceInterfaceInPath(const rrlib::uri::tPath& path, const std::string& new_interface) 
    98103{ 
    99104  if (path.Size() < 2) 
     
    109114  return rrlib::uri::tPath(path.IsAbsolute(), path_components.begin(), path_components.end()); 
    110115} 
     116 
     117/*! Specialized tFinstructable class to realize include mechanism */ 
     118class tIncludeFinstructable : public tFinstructable 
     119{ 
     120public: 
     121  /*! 
     122   * Root framework element that this annotation belongs to 
     123   * Optional setting that overrides element that annotation is attached to 
     124   */ 
     125  core::tFrameworkElement* root_framework_element = nullptr; 
     126  std::string xml_file; 
     127  core::tFrameworkElement* origin = nullptr; 
     128 
     129  tIncludeFinstructable() : tFinstructable(xml_file) 
     130  {} 
     131}; 
     132 
     133// Returns tIncludeFinstructable if 'finstructable' is one - otherwise nullptr 
     134tIncludeFinstructable* IncludeFinstructable(tFinstructable* finstructable) 
     135{ 
     136  return typeid(*finstructable) == typeid(tIncludeFinstructable) ? static_cast<tIncludeFinstructable*>(finstructable) : nullptr; 
     137} 
     138const tIncludeFinstructable* IncludeFinstructable(const tFinstructable* finstructable) 
     139{ 
     140  return typeid(*finstructable) == typeid(tIncludeFinstructable) ? static_cast<const tIncludeFinstructable*>(finstructable) : nullptr; 
     141} 
     142 
     143 
     144/*! Framework element with create action for inclusion of finstructable XML files */ 
     145class tIncludeElement : public core::tFrameworkElement 
     146{ 
     147public: 
     148  tIncludeElement(core::tFrameworkElement* parent, const std::string& name, const std::string& xml_file) : 
     149    tFrameworkElement(GetIncludesParent(parent, true), xml_file), 
     150    xml_file(xml_file) 
     151  { 
     152    tFinstructable::Include(*parent, xml_file, this); 
     153  } 
     154 
     155  std::string xml_file; 
     156 
     157  void OnManagedDelete() override 
     158  { 
     159    // Remove the whole included structure 
     160    auto parent = GetParent(); 
     161    parent = parent ? parent->GetParent() : parent; 
     162    if (parent && parent->IsReady()) 
     163    { 
     164      for (auto it = parent->SubElementsBegin(); it != parent->SubElementsEnd(); ++it) 
     165      { 
     166        tOriginDataAnnotation* annotation = it->GetAnnotation<tOriginDataAnnotation>(); 
     167        if (annotation && annotation->Data().origin == this) 
     168        { 
     169          it->ManagedDelete(); 
     170        } 
     171      } 
     172    } 
     173  } 
     174 
     175  static core::tFrameworkElement* GetIncludesParent(core::tFrameworkElement* parent, bool create_if_it_does_not_exist) 
     176  { 
     177    auto result = parent->GetChild("Includes"); 
     178    if ((!result) && create_if_it_does_not_exist) 
     179    { 
     180      result = new core::tFrameworkElement(parent, "Includes"); 
     181      result->Init(); 
     182    } 
     183    return result; 
     184  } 
     185}; 
     186 
     187tConstructorCreateModuleAction<tIncludeElement, std::string> cINCLUDE_CREATE_ACTION("Include", "File"); 
     188 
     189 
     190bool HasNonDefaultFinstructInfo(const parameters::internal::tParameterInfo& info) 
     191{ 
     192  for (auto & setting : info.Settings()) 
     193  { 
     194    if (setting.high_precedence && setting.origin == nullptr) 
     195    { 
     196      return true; 
     197    } 
     198  } 
     199  return false; 
     200} 
     201 
     202} 
     203 
    111204 
    112205tFinstructable::tFinstructable(const std::string& xml_file) : 
     
    168261} 
    169262 
     263core::tFrameworkElement* tFinstructable::GetFrameworkElement() const 
     264{ 
     265  auto include_instance = IncludeFinstructable(this); 
     266  return include_instance ? include_instance->root_framework_element : this->GetAnnotated<core::tFrameworkElement>(); 
     267} 
     268 
    170269std::string tFinstructable::GetLogDescription() const 
    171270{ 
     
    187286  } 
    188287  return s; 
     288} 
     289 
     290void tFinstructable::Include(core::tFrameworkElement& parent, const std::string& xml_file, core::tFrameworkElement* origin) 
     291{ 
     292  tIncludeFinstructable temp_finstructable; 
     293  temp_finstructable.xml_file = xml_file; 
     294  temp_finstructable.root_framework_element = &parent; 
     295  temp_finstructable.origin = origin; 
     296  temp_finstructable.LoadXml(); 
    189297} 
    190298 
     
    227335    } 
    228336    created = action.CreateModule(parent, name, spl); 
    229     SetFinstructed(*created, action, spl); 
     337    tOriginData data; 
     338    auto include_instance = IncludeFinstructable(this); 
     339    if (include_instance && include_instance->origin) 
     340    { 
     341      data.origin = include_instance->origin; 
     342      SetFinstructed(*created, action, spl, data); 
     343    } 
     344    else if (!include_instance) 
     345    { 
     346      SetFinstructed(*created, action, spl, data); 
     347    } 
    230348    if (parameters) 
    231349    { 
     
    273391  else 
    274392  { 
     393    auto include_instance = IncludeFinstructable(this); 
     394    bool high_precendence = include_instance == nullptr; 
     395    auto origin = include_instance ? include_instance->origin : nullptr; 
    275396    if (outermost_group && node.HasAttribute("cmdline") && (!IsResponsibleForConfigFileConnections(parameter_port))) 
    276397    { 
    277       pi->SetCommandLineOption(node.GetStringAttribute("cmdline")); 
     398      pi->SetCommandLineOption(node.GetStringAttribute("cmdline"), high_precendence, origin); 
    278399    } 
    279400    else 
    280401    { 
    281       pi->Deserialize(node, true, outermost_group); 
     402      pi->Deserialize(node, high_precendence, outermost_group, origin); 
    282403    } 
    283404    try 
     
    295416{ 
    296417  { 
     418    auto include_instance = IncludeFinstructable(this); 
     419    tOriginData origin_data; 
     420    if (include_instance && include_instance->origin) 
     421    { 
     422      origin_data.origin = include_instance->origin; 
     423    } 
     424 
    297425    rrlib::thread::tLock lock2(core::tRuntimeEnvironment::GetInstance().GetStructureMutex()); 
    298426    try 
     
    359487          Instantiate(*node, GetFrameworkElement()); 
    360488        } 
     489        if (name == "include") 
     490        { 
     491          std::string file; 
     492          try 
     493          { 
     494            file = node->GetStringAttribute("file"); 
     495            auto created = new tIncludeElement(this->GetFrameworkElement(), file, file); 
     496            origin_data.order = std::chrono::steady_clock::now().time_since_epoch().count(); 
     497            if (!include_instance) 
     498            { 
     499              created->SetFlag(tFlag::FINSTRUCTED); 
     500            } 
     501            created->EmplaceAnnotation<tOriginDataAnnotation>(origin_data); 
     502            created->Init(); 
     503          } 
     504          catch (const std::exception& e) 
     505          { 
     506            FINROC_LOG_PRINT(ERROR, "Including ", file, " failed: ", e); 
     507          } 
     508        } 
    361509      } 
    362510 
     
    373521            try 
    374522            { 
    375               core::tPortGroup& loaded_interface = editable_interfaces->LoadInterfacePorts(*node); 
     523              auto include_instance = IncludeFinstructable(this); 
     524              core::tPortGroup& loaded_interface = editable_interfaces->LoadInterfacePorts(*node, !include_instance, include_instance ? include_instance->origin : nullptr); 
    376525 
    377526              // Move RPC port to suitable interfaces when loading legacy files 
     
    418567          } 
    419568        } 
    420         else if (name == "element") 
     569        else if (name == "element" || name == "include") 
    421570        { 
    422571          // already instantiated 
     
    443592              destination_uri_parsed.path = rrlib::uri::tPath(destination_string); 
    444593            } 
    445             core::tUriConnectOptions connect_options(core::tConnectionFlag::FINSTRUCTED); 
     594            core::tUriConnectOptions connect_options; 
     595            connect_options.flags.Set(core::tConnectionFlag::FINSTRUCTED, !static_cast<bool>(include_instance));  // TODO attach origin data to connectors also 
    446596            if (node->HasAttribute("flags")) 
    447597            { 
     
    713863    bool is_responsible_for_parameter_links = IsResponsibleForConfigFileConnections(*port); 
    714864 
    715     if (info && info->HasNonDefaultFinstructInfo() && (is_responsible_for_parameter_links || (outermost_group && info->GetCommandLineOption().length()))) 
     865    if (info && HasNonDefaultFinstructInfo(*info) && (is_responsible_for_parameter_links || (outermost_group && info->GetCommandLineOption().length()))) 
    716866    { 
    717867      // Save Parameter 
     
    725875      else 
    726876      { 
    727         info->Serialize(parameter_node, true, outermost_group); 
     877        info->Serialize(parameter_node, true, outermost_group, nullptr); 
    728878      } 
    729879      result = true; 
     
    10571207void tFinstructable::SerializeChildren(rrlib::xml::tNode& node, tFrameworkElement& current) 
    10581208{ 
    1059   for (auto child = current.ChildrenBegin(); child != current.ChildrenEnd(); ++child) 
    1060   { 
     1209  std::vector<std::pair<tOriginData, core::tFrameworkElement*>> children_to_serialize; 
     1210  std::vector<core::tFrameworkElement*> elements_to_scan = { &current }; 
     1211  auto include_parent = tIncludeElement::GetIncludesParent(&current, false); 
     1212  if (include_parent) 
     1213  { 
     1214    elements_to_scan.push_back(include_parent); 
     1215  } 
     1216  for (auto element_to_scan : elements_to_scan) 
     1217  { 
     1218    for (auto child = element_to_scan->ChildrenBegin(); child != element_to_scan->ChildrenEnd(); ++child) 
     1219    { 
     1220      auto origin_data = child->GetAnnotation<tOriginDataAnnotation>(); 
     1221      if (child->IsReady() && child->GetFlag(tFlag::FINSTRUCTED) && origin_data && (child->GetAnnotation<parameters::internal::tStaticParameterList>() || typeid(*child) == typeid(tIncludeElement))) 
     1222      { 
     1223        children_to_serialize.emplace_back(origin_data->Data(), &*child); 
     1224      } 
     1225    } 
     1226  } 
     1227 
     1228  std::sort(children_to_serialize.begin(), children_to_serialize.end()); 
     1229 
     1230  for (auto & child_entry : children_to_serialize) 
     1231  { 
     1232    auto child = child_entry.second; 
     1233 
     1234    if (typeid(*child) == typeid(tIncludeElement)) 
     1235    { 
     1236      rrlib::xml::tNode& n = node.AddChildNode("include"); 
     1237      n.SetAttribute("file", static_cast<tIncludeElement*>(child)->xml_file); 
     1238      continue; 
     1239    } 
     1240 
    10611241    parameters::internal::tStaticParameterList* spl = child->GetAnnotation<parameters::internal::tStaticParameterList>(); 
    10621242    tConstructorParameters* cps = child->GetAnnotation<tConstructorParameters>(); 
    1063     if (child->IsReady() && child->GetFlag(tFlag::FINSTRUCTED)) 
    1064     { 
    1065       // serialize framework element 
    1066       rrlib::xml::tNode& n = node.AddChildNode("element"); 
    1067       n.SetAttribute("name", child->GetName()); 
    1068       tCreateFrameworkElementAction* cma = tCreateFrameworkElementAction::GetConstructibleElements()[spl->GetCreateAction()]; 
    1069       n.SetAttribute("group", cma->GetModuleGroup().ToString()); 
    1070       //if (boost::ends_with(cma->GetModuleGroup(), ".so")) 
    1071       //{ 
    1072       AddDependency(cma->GetModuleGroup()); 
    1073       //} 
    1074       n.SetAttribute("type", cma->GetName()); 
    1075       if (cps != nullptr) 
    1076       { 
    1077         rrlib::xml::tNode& pn = n.AddChildNode("constructor"); 
    1078         cps->Serialize(pn, true); 
    1079       } 
    1080       if (spl != nullptr) 
    1081       { 
    1082         rrlib::xml::tNode& pn = n.AddChildNode("parameters"); 
    1083         spl->Serialize(pn, true); 
    1084       } 
    1085  
    1086       // serialize its children 
    1087       if (!child->GetFlag(tFlag::FINSTRUCTABLE_GROUP)) 
    1088       { 
    1089         SerializeChildren(n, *child); 
    1090       } 
    1091     } 
    1092   } 
    1093 } 
    1094  
    1095 void tFinstructable::SetFinstructed(tFrameworkElement& fe, tCreateFrameworkElementAction& create_action, tConstructorParameters* params) 
     1243 
     1244    // serialize framework element 
     1245    rrlib::xml::tNode& n = node.AddChildNode("element"); 
     1246    n.SetAttribute("name", child->GetName()); 
     1247    assert(spl); 
     1248    tCreateFrameworkElementAction* cma = tCreateFrameworkElementAction::GetConstructibleElements()[spl->GetCreateAction()]; 
     1249    n.SetAttribute("group", cma->GetModuleGroup().ToString()); 
     1250    //if (boost::ends_with(cma->GetModuleGroup(), ".so")) 
     1251    //{ 
     1252    AddDependency(cma->GetModuleGroup()); 
     1253    //} 
     1254    n.SetAttribute("type", cma->GetName()); 
     1255    if (cps) 
     1256    { 
     1257      rrlib::xml::tNode& pn = n.AddChildNode("constructor"); 
     1258      cps->Serialize(pn, true); 
     1259    } 
     1260    if (spl) 
     1261    { 
     1262      rrlib::xml::tNode& pn = n.AddChildNode("parameters"); 
     1263      spl->Serialize(pn, true); 
     1264    } 
     1265 
     1266    // serialize its children 
     1267    if (!child->GetFlag(tFlag::FINSTRUCTABLE_GROUP)) 
     1268    { 
     1269      SerializeChildren(n, *child); 
     1270    } 
     1271  } 
     1272} 
     1273 
     1274void tFinstructable::SetFinstructed(tFrameworkElement& fe, tCreateFrameworkElementAction& create_action, tConstructorParameters* params, tOriginData origin_data) 
    10961275{ 
    10971276  assert(!fe.GetFlag(tFlag::FINSTRUCTED) && (!fe.IsReady())); 
     
    11061285    } 
    11071286  } 
    1108   fe.SetFlag(tFlag::FINSTRUCTED); 
     1287  bool include_finstructed = origin_data.origin; 
     1288  fe.SetFlag(tFlag::FINSTRUCTED, (!include_finstructed)); 
    11091289  if (params) 
    11101290  { 
    11111291    fe.AddAnnotation<tConstructorParameters>(*params); 
    11121292  } 
     1293 
     1294  origin_data.order = std::chrono::steady_clock::now().time_since_epoch().count(); 
     1295  fe.EmplaceAnnotation<tOriginDataAnnotation>(origin_data); 
    11131296} 
    11141297 
  • tFinstructable.h

    r90 r134  
    5454//---------------------------------------------------------------------- 
    5555#include "plugins/runtime_construction/tCreateFrameworkElementAction.h" 
     56#include "plugins/runtime_construction/tOriginData.h" 
    5657 
    5758//---------------------------------------------------------------------- 
     
    116117 
    117118  /*! 
     119   * "Includes" finstructable XML file: Adds all structure defined in XML file to specified parent element. 
     120   * Note that the created structure is not marked 'finstructed' (so that saving the main file does not suddenly include all of it). 
     121   * 
     122   * \param parent Framework element to add structure to 
     123   * \param xml_file Finstructable XML file containing structure to add 
     124   * \param origin Origin (optional). If set, adds tOriginDataAnnotation with this origin to created elements. 
     125   */ 
     126  static void Include(core::tFrameworkElement& parent, const std::string& xml_file, core::tFrameworkElement* origin = nullptr); 
     127 
     128  /*! 
    118129   * Loads and instantiates contents of xml file 
    119130   * 
     
    145156   * \param create_action Action with which framework element was created 
    146157   * \param params Parameters that module was created with (may be null) 
    147    */ 
    148   static void SetFinstructed(core::tFrameworkElement& fe, tCreateFrameworkElementAction& create_action, tConstructorParameters* params); 
     158   * \param origin_data Origin data to attach (if not set, order will be set to steady_clock time) 
     159   */ 
     160  static void SetFinstructed(core::tFrameworkElement& fe, tCreateFrameworkElementAction& create_action, tConstructorParameters* params, tOriginData origin_data = tOriginData()); 
    149161 
    150162  /*! 
     
    202214   * \return Root framework element that this annotation belongs to 
    203215   */ 
    204   core::tFrameworkElement* GetFrameworkElement() const 
    205   { 
    206     return this->GetAnnotated<core::tFrameworkElement>(); 
    207   } 
     216  core::tFrameworkElement* GetFrameworkElement() const; 
    208217 
    209218  /*! 
  • tPortCreationList.cpp

    r126 r134  
    108108  selectable_create_options(), 
    109109  list(), 
    110   io_vector(NULL), 
     110  io_vector(nullptr), 
    111111  flags(tFlags()), 
    112   ports_flagged_finstructed(true) 
     112  ports_flagged_finstructed(true), 
     113  origin(nullptr) 
    113114{} 
    114115 
    115 tPortCreationList::tPortCreationList(core::tFrameworkElement& port_group, tFlags flags, const tPortCreateOptions& selectable_create_options, bool ports_flagged_finstructed) : 
     116tPortCreationList::tPortCreationList(core::tFrameworkElement& port_group, tFlags flags, const tPortCreateOptions& selectable_create_options, bool ports_flagged_finstructed, const tOrigin* origin) : 
    116117  selectable_create_options(), 
    117118  list(), 
    118119  io_vector(&port_group), 
    119120  flags(flags | (ports_flagged_finstructed ? tFlag::FINSTRUCTED : tFlag::PORT)), 
    120   ports_flagged_finstructed(ports_flagged_finstructed) 
     121  ports_flagged_finstructed(ports_flagged_finstructed), 
     122  origin(origin) 
    121123{ 
    122124  if (!flags.Get(tFlag::SHARED) && selectable_create_options.Get(tPortCreateOption::SHARED)) 
     
    133135{ 
    134136  rrlib::thread::tLock lock(io_vector->GetStructureMutex()); 
    135   CheckPort(NULL, *io_vector, flags, name, dt, create_options, NULL); 
     137  CheckPort(nullptr, *io_vector, flags, name, dt, create_options, nullptr, this->GetSize()); 
    136138} 
    137139 
     
    139141{ 
    140142  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); 
     143  tGetPortsResult ports1; 
     144  GetPorts(*this->io_vector, ports1, ports_flagged_finstructed, origin); 
     145  tGetPortsResult ports2; 
     146  GetPorts(io_vector_, ports2, ports_flagged_finstructed, origin); 
    145147 
    146148  for (size_t i = 0u; i < ports1.size(); i++) 
    147149  { 
    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); 
     150    core::tAbstractPort* ap1 = ports1[i].second; 
     151    core::tAbstractPort* ap2 = i < ports2.size() ? ports2[i].second : nullptr; 
     152    CheckPort(ap2, io_vector_, flags_, ap1->GetName(), ap1->GetDataType(), ToPortCreateOptions(ap1->GetAllFlags(), selectable_create_options), ap1, i); 
    151153  } 
    152154  for (size_t i = ports1.size(); i < ports2.size(); i++) 
    153155  { 
    154     ports2[i]->ManagedDelete(); 
     156    ports2[i].second->ManagedDelete(); 
    155157  } 
    156158} 
    157159 
    158160void 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) 
     161                                  const std::string& name, rrlib::rtti::tType type, const tPortCreateOptions& create_options, core::tAbstractPort* prototype, size_t index) 
    160162{ 
    161163  if (existing_port && existing_port->GetName() == name && existing_port->GetDataType() == type && 
     
    164166    bool create_output_port = create_options.Get(tPortCreateOption::OUTPUT) || flags.Get(tFlag::OUTPUT_PORT); 
    165167    bool create_shared_port = create_options.Get(tPortCreateOption::SHARED) || flags.Get(tFlag::SHARED); 
     168    auto annotation = existing_port->GetAnnotation<tOriginDataAnnotation>(); 
    166169    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))) 
     170        ((!selectable_create_options.Get(tPortCreateOption::SHARED)) || (existing_port->GetFlag(tFlag::SHARED) == create_shared_port)) && annotation) 
    168171    { 
    169172      // port is as it should be 
     173      annotation->Data().order = index;  // possibly adjust index 
    170174      return; 
    171175    } 
     
    186190  FINROC_LOG_PRINT_TO(port_creation_list, DEBUG_VERBOSE_1, "Creating port ", name, " in IOVector ", io_vector); 
    187191  core::tAbstractPort* created_port = core::tPortFactory::CreatePort(name, io_vector, type, flags); 
    188   if (created_port != NULL) 
    189   { 
     192  if (created_port) 
     193  { 
     194    tOriginData origin_data; 
     195    origin_data.origin = origin; 
     196    origin_data.order = static_cast<tOriginData::tOrder>(index); 
     197    created_port->EmplaceAnnotation<tOriginDataAnnotation>(origin_data); 
    190198    created_port->Init(); 
    191199  } 
     
    196204} 
    197205 
    198 void tPortCreationList::GetPorts(const core::tFrameworkElement& elem, std::vector<core::tAbstractPort*>& result, bool finstructed_ports_only) 
     206void tPortCreationList::GetPorts(const core::tFrameworkElement& elem, tGetPortsResult& result, bool ports_flagged_finstructed, const tOrigin* origin) 
    199207{ 
    200208  result.clear(); 
    201209  for (auto it = elem.ChildPortsBegin(); it != elem.ChildPortsEnd(); ++it) 
    202210  { 
    203     if ((!finstructed_ports_only) || it->GetFlag(tFlag::FINSTRUCTED)) 
    204     { 
    205       result.push_back(&(*it)); 
    206     } 
     211    tOriginDataAnnotation* origin_annotation = it->GetAnnotation<tOriginDataAnnotation>(); 
     212    if (origin_annotation && ports_flagged_finstructed == it->GetFlag(tFlag::FINSTRUCTED) && origin_annotation->Data().origin == origin) 
     213    { 
     214      result.emplace_back(origin_annotation->Data().order, &(*it)); 
     215    } 
     216  } 
     217 
     218  std::sort(result.begin(), result.end()); 
     219 
     220  size_t expected_index = 0; 
     221  for (auto & entry : result) 
     222  { 
     223    if (static_cast<size_t>(entry.first) != expected_index) 
     224    { 
     225      FINROC_LOG_PRINT(WARNING, "Ports do not have expected indices. Adjusting."); 
     226      expected_index = 0; 
     227      for (auto & entry : result) 
     228      { 
     229        entry.second->GetAnnotation<tOriginDataAnnotation>()->Data().order = expected_index; 
     230        expected_index++; 
     231      } 
     232      break; 
     233    } 
     234    expected_index++; 
    207235  } 
    208236} 
     
    215243  } 
    216244  int count = 0; 
    217   for (auto it = io_vector->ChildrenBegin(); it != io_vector->ChildrenEnd(); ++it) 
    218   { 
    219     count++; 
     245  for (auto it = io_vector->ChildPortsBegin(); it != io_vector->ChildPortsEnd(); ++it) 
     246  { 
     247    tOriginDataAnnotation* origin_annotation = it->GetAnnotation<tOriginDataAnnotation>(); 
     248    if (origin_annotation && ports_flagged_finstructed == it->GetFlag(tFlag::FINSTRUCTED) && origin_annotation->Data().origin == origin) 
     249    { 
     250      count++; 
     251    } 
    220252  } 
    221253  return count; 
     
    224256void tPortCreationList::InitialSetup(core::tFrameworkElement& managed_io_vector, tFlags port_creation_flags, const tPortCreateOptions& selectable_create_options) 
    225257{ 
    226   assert((io_vector == NULL || io_vector == &managed_io_vector) && list.empty()); 
     258  assert((io_vector == nullptr || io_vector == &managed_io_vector) && list.empty()); 
    227259  io_vector = &managed_io_vector; 
    228260  flags = port_creation_flags; 
     
    243275{ 
    244276  stream.WriteByte(list.selectable_create_options.Raw()); 
    245   if (list.io_vector == NULL) 
     277  if (!list.io_vector) 
    246278  { 
    247279    int size = list.list.size(); 
     
    258290  { 
    259291    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); 
     292    tPortCreationList::tGetPortsResult ports; 
     293    list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed, list.origin); 
    262294    int size = ports.size(); 
    263295    stream.WriteInt(size); 
    264296    for (int i = 0; i < size; i++) 
    265297    { 
    266       core::tAbstractPort* p = ports[i]; 
     298      core::tAbstractPort* p = ports[i].second; 
    267299      stream.WriteString(p->GetName()); 
    268300      stream.WriteString(p->GetDataType().GetName()); 
     
    275307rrlib::serialization::tInputStream& operator >> (rrlib::serialization::tInputStream& stream, tPortCreationList& list) 
    276308{ 
    277   if (list.io_vector == NULL) 
     309  if (!list.io_vector) 
    278310  { 
    279311    list.selectable_create_options = tPortCreateOptions(stream.ReadByte()); 
     
    292324    stream.ReadByte(); // skip selectable create options, as this is not defined by finstruct 
    293325    size_t size = stream.ReadInt(); 
    294     std::vector<core::tAbstractPort*> existing_ports; 
    295     list.GetPorts(*list.io_vector, existing_ports, list.ports_flagged_finstructed); 
     326    tPortCreationList::tGetPortsResult existing_ports; 
     327    list.GetPorts(*list.io_vector, existing_ports, list.ports_flagged_finstructed, list.origin); 
    296328    for (size_t i = 0u; i < size; i++) 
    297329    { 
     
    306338      tPortCreateOptions create_options(stream.ReadByte()); 
    307339 
    308       core::tAbstractPort* existing_port_with_this_name = NULL; 
     340      core::tAbstractPort* existing_port_with_this_name = nullptr; 
    309341      for (auto it = existing_ports.begin(); it != existing_ports.end(); ++it) 
    310342      { 
    311         if ((*it)->GetName() == name) 
     343        if (it->second->GetName() == name) 
    312344        { 
    313           existing_port_with_this_name = *it; 
     345          existing_port_with_this_name = it->second; 
    314346          existing_ports.erase(it); 
    315347          break; 
    316348        } 
    317349      } 
    318       list.CheckPort(existing_port_with_this_name, *list.io_vector, list.flags, name, type, create_options, NULL); 
     350      list.CheckPort(existing_port_with_this_name, *list.io_vector, list.flags, name, type, create_options, nullptr, i); 
    319351    } 
    320352 
     
    322354    for (size_t i = 0; i < existing_ports.size(); i++) 
    323355    { 
    324       existing_ports[i]->ManagedDelete(); 
     356      existing_ports[i].second->ManagedDelete(); 
    325357    } 
    326358  } 
     
    340372    node.SetAttribute("showOutputSelection", list.selectable_create_options.Get(tPortCreateOption::OUTPUT)); 
    341373  } 
    342   std::vector<core::tAbstractPort*> ports; 
    343   list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed); 
     374  tPortCreationList::tGetPortsResult ports; 
     375  list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed, list.origin); 
    344376  int size = ports.size(); 
    345377  for (int i = 0; i < size; i++) 
    346378  { 
    347     core::tAbstractPort* p = ports[i]; 
     379    core::tAbstractPort* p = ports[i].second; 
    348380    rrlib::xml::tNode& child = node.AddChildNode("port"); 
    349381    child.SetAttribute("name", p->GetName()); 
     
    370402 
    371403  rrlib::thread::tLock lock(list.io_vector->GetStructureMutex()); 
    372   if (!list.ports_flagged_finstructed) 
     404  if ((!list.ports_flagged_finstructed) && node.HasAttribute("showOutputSelection")) 
    373405  { 
    374406    list.selectable_create_options.Set(tPortCreateOption::OUTPUT, node.GetBoolAttribute("showOutputSelection")); 
    375407  } 
    376   std::vector<core::tAbstractPort*> ports; 
    377   list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed); 
     408  tPortCreationList::tGetPortsResult ports; 
     409  list.GetPorts(*list.io_vector, ports, list.ports_flagged_finstructed, list.origin); 
    378410  size_t i = 0u; 
    379411  std::set<std::string> missing_types; 
    380412  for (rrlib::xml::tNode::const_iterator port = node.ChildrenBegin(); port != node.ChildrenEnd(); ++port, ++i) 
    381413  { 
    382     core::tAbstractPort* ap = i < ports.size() ? ports[i] : NULL; 
     414    core::tAbstractPort* ap = i < ports.size() ? ports[i].second : nullptr; 
    383415    std::string port_name = port->Name(); 
    384416    assert(port_name.compare("port") == 0); 
     
    408440    } 
    409441 
    410     list.CheckPort(ap, *list.io_vector, list.flags, port->GetStringAttribute("name"), dt, create_options, NULL); 
     442    list.CheckPort(ap, *list.io_vector, list.flags, port->GetStringAttribute("name"), dt, create_options, nullptr, i); 
    411443  } 
    412444  for (; i < ports.size(); i++) 
    413445  { 
    414     ports[i]->ManagedDelete(); 
     446    ports[i].second->ManagedDelete(); 
    415447  } 
    416448 
  • tPortCreationList.h

    r109 r134  
    4848//---------------------------------------------------------------------- 
    4949#include "plugins/runtime_construction/tDataTypeReference.h" 
     50#include "plugins/runtime_construction/tOriginData.h" 
    5051 
    5152//---------------------------------------------------------------------- 
     
    102103public: 
    103104 
     105  typedef tOriginData::tOrigin tOrigin; 
     106 
     107 
    104108  tPortCreationList(); 
    105109 
     
    109113   * \param selectable_create_options Which creation options should be visible and selectable in finstruct? 
    110114   * \param ports_flagged_finstructed Deal only with ports flagged finstructed? 
     115   * \param origin Origin for which to create and manage ports (all ports that do no match origin are not touched) 
    111116   */ 
    112117  tPortCreationList(core::tFrameworkElement& port_group, tFlags flags, 
    113                     const tPortCreateOptions& selectable_create_options, bool ports_flagged_finstructed = true); 
     118                    const tPortCreateOptions& selectable_create_options, bool ports_flagged_finstructed = true, const tOrigin* origin = nullptr); 
    114119 
    115120  tPortCreationList(tPortCreationList &&) = delete; 
     
    170175  friend const rrlib::xml::tNode& operator >> (const rrlib::xml::tNode& node, tPortCreationList& list); 
    171176 
     177  typedef std::vector<std::pair<tOriginData::tOrder, core::tAbstractPort*>> tGetPortsResult; 
     178 
    172179  /*! 
    173180   * Entry in list 
     
    211218   */ 
    212219  bool ports_flagged_finstructed; 
     220 
     221  /*! Origin for which to create and manage ports (all ports that do no match origin are not touched) */ 
     222  const tOrigin* origin; 
    213223 
    214224  /*! 
     
    222232   * \param create_options Selected create options for port 
    223233   * \param prototype Port prototype (only interesting for listener) 
     234   * \param index Index for origin data 
    224235   */ 
    225236  void CheckPort(core::tAbstractPort* existing_port, core::tFrameworkElement& io_vector, tFlags flags, const std::string& name, 
    226                  rrlib::rtti::tType type, const tPortCreateOptions& create_options, core::tAbstractPort* prototype); 
    227  
    228   /*! 
    229    * Returns all child ports of specified framework element 
     237                 rrlib::rtti::tType type, const tPortCreateOptions& create_options, core::tAbstractPort* prototype, size_t index); 
     238 
     239  /*! 
     240   * Returns all child ports of specified framework element with specified origin 
    230241   * 
    231242   * \param elem Framework Element 
    232243   * \param result List containing result 
    233    * \param finstructed_ports_only Only retrieve finstructed ports? 
    234    */ 
    235   static void GetPorts(const core::tFrameworkElement& elem, std::vector<core::tAbstractPort*>& result, bool finstructed_ports_only); 
     244   * \param ports_flagged_finstructed Whether to return ports with FINSTRUCTED flag set - or without 
     245   * \param origin Origin ports must have 
     246   */ 
     247  static void GetPorts(const core::tFrameworkElement& elem, tGetPortsResult& result, bool ports_flagged_finstructed, const tOrigin* origin); 
    236248}; 
    237249 
Note: See TracChangeset for help on using the changeset viewer.