Changeset 469:4a5dd2bd8876 in finroc_core


Ignore:
Timestamp:
12.02.2020 14:40:31 (2 weeks ago)
Author:
Max Reichardt <max.reichardt@…>
Branch:
17.03
Children:
470:28f8f4c3acbd, 471:2de952eeb1d4
Parents:
466:3d7ce7619657 (diff), 468:a1bfec1a20ae (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Phase:
public
Message:

Merge with 14.08

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • tFrameworkElement.cpp

    r449 r469  
    147147  } 
    148148 
     149  assert((handle >= internal::tFrameworkElementRegister::cFIRST_PORT_HANDLE) == flags.Get(tFlag::PORT) && "Invalid handle assigned"); 
    149150  FINROC_LOG_PRINT(DEBUG_VERBOSE_1, "Constructing tFrameworkElement (" , this, ")"); 
    150151} 
  • tFrameworkElement.cpp

    r468 r469  
    7777const size_t MAX_HIERARCHY_DEPTH = 100; 
    7878 
     79std::unique_ptr<const tFrameworkElement::tLink> tFrameworkElement::cINVALID_LINK; 
     80 
    7981//---------------------------------------------------------------------- 
    8082// Implementation 
     
    9799}; 
    98100 
     101/*! Obtain number of ancestors of link */ 
     102static size_t CountNumberOfAncestors(const tFrameworkElement::tLink& link, bool include_runtime = false) 
     103{ 
     104  core::tFrameworkElement* parent = link.GetParent(); 
     105  size_t count = 0; 
     106  while (parent && ((!parent->IsRuntime()) || include_runtime)) 
     107  { 
     108    count++; 
     109    parent = parent->GetParent(); 
     110  } 
     111  return count; 
     112} 
     113 
    99114} 
    100115 
    101116tFrameworkElement::tFrameworkElement(tFrameworkElement* parent, const tString& name, tFlags flags) : 
    102   handle(flags.Get(tFlag::RUNTIME) ? 0 : tRuntimeEnvironment::GetInstance().RegisterElement(*this, flags.Get(tFlag::PORT))), 
     117  handle(flags.Get(tFlag::RUNTIME) && (!flags.Get(tFlag::PORT)) ? 0 : tRuntimeEnvironment::GetInstance().RegisterElement(*this, flags.Get(tFlag::PORT))), 
    103118  primary(*this), 
    104119#ifndef RRLIB_SINGLE_THREADED 
     
    119134  } 
    120135 
    121   if (!GetFlag(tFlag::RUNTIME)) 
     136  if (!IsRuntime()) 
    122137  { 
    123138    if (!parent) 
     
    126141    } 
    127142    parent->AddChild(primary); 
     143  } 
     144  else 
     145  { 
     146    cINVALID_LINK.reset(new tLink(*this)); 
    128147  } 
    129148 
     
    134153tFrameworkElement::~tFrameworkElement() 
    135154{ 
    136   assert((GetFlag(tFlag::DELETED) || GetFlag(tFlag::RUNTIME)) && "Framework element was not deleted with ManagedDelete()"); 
     155  if (!(GetFlag(tFlag::DELETED) || IsRuntime())) 
     156  { 
     157    FINROC_LOG_PRINT(ERROR, "Framework element '", GetName(), "' was not deleted with ManagedDelete()"); 
     158    abort(); 
     159  } 
    137160  FINROC_LOG_PRINT(DEBUG_VERBOSE_1, "FrameworkElement destructor (" , this, ")"); 
    138   if (!GetFlag(tFlag::RUNTIME)) 
    139   { 
    140     // synchronizes on runtime - so no elements will be deleted while runtime is locked 
     161  if (!IsRuntime()) 
     162  { 
     163    // synchronizes on runtime - to ensure that no elements (e.g. this one) are deleted while possibly someone else has runtime locked 
    141164    rrlib::thread::tLock lock(GetStructureMutex()); 
    142165    //GetRuntime().UnregisterElement(*this); 
     
    230253bool tFrameworkElement::AllParentsReady() const 
    231254{ 
    232   if (GetFlag(tFlag::RUNTIME)) 
     255  if (IsRuntime()) 
    233256  { 
    234257    return true; 
     
    275298void tFrameworkElement::CheckForNameClash(const tLink& link) const 
    276299{ 
    277   if (!tRuntimeSettings::DuplicateQualifiedNamesAllowed() && link.parent && (!link.GetChild().GetFlag(tFlag::NETWORK_ELEMENT))) // we cannot influence naming of elements in other runtime environments 
     300  if (link.parent && (!link.GetChild().GetFlag(tFlag::NETWORK_ELEMENT))) // we cannot influence naming of elements in other runtime environments 
    278301  { 
    279302    for (auto it = link.parent->ChildrenBegin(); it != link.parent->ChildrenEnd(); ++it) 
     
    281304      if (it->IsReady() && it->GetName().compare(primary.GetName()) == 0) 
    282305      { 
    283         FINROC_LOG_PRINT(ERROR, "Framework elements with the same qualified names are not allowed ('", it->GetQualifiedName(), 
    284                          "'), since this causes undefined behavior with port connections by qualified names (e.g. in fingui or in finstructable groups). Apart from manually choosing another name, there are two ways to solve this:\n", 
    285                          "  1) Set the tFrameworkElementFlags::AUTO_RENAME flag when constructing parent framework element.\n", 
    286                          "  2) Explicitly allow duplicate names by calling tRuntimeSettings::AllowDuplicateQualifiedNames() and be careful."); 
     306        FINROC_LOG_PRINT(ERROR, "Framework elements with the same qualified names are not allowed ('", (*it), 
     307                         "'), since this causes undefined behavior with port connections by URIs (e.g. in fingui or in finstructable groups). Apart from manually choosing another name, you can also set the tFrameworkElementFlags::AUTO_RENAME flag when constructing the parent framework element."); 
    287308        abort(); 
    288309      } 
    289310    } 
    290311  } 
     312} 
     313 
     314size_t tFrameworkElement::ChildCount() const 
     315{ 
     316  size_t count = 0; 
     317  for (auto it = ChildrenBegin(); it != ChildrenEnd(); ++it) 
     318  { 
     319    count++; 
     320  } 
     321  return count; 
    291322} 
    292323 
     
    319350      if (IsDeleted()) 
    320351      { 
    321         return NULL; 
     352        return nullptr; 
    322353      } 
    323354      if ((*it)->GetChild().IsDeleted()) 
     
    331362    } 
    332363  } 
    333   return NULL; 
    334 } 
    335  
    336 tFrameworkElement* tFrameworkElement::GetChildElement(const tString& name, bool only_globally_unique_children) 
    337 { 
    338   return GetChildElement(name, 0, only_globally_unique_children, GetRuntime()); 
    339 } 
    340  
    341 tFrameworkElement* tFrameworkElement::GetChildElement(const tString& name, int name_index, bool only_globally_unique_children, tFrameworkElement& root) 
    342 { 
    343   // lock runtime (might not be absolutely necessary... ensures, however, that result is valid) 
    344   tLock lock(GetStructureMutex()); 
    345  
     364  return nullptr; 
     365} 
     366 
     367tFrameworkElement* tFrameworkElement::GetDescendant(const tPath& path) 
     368{ 
     369  return GetDescendant(path, 0, GetRuntime()); 
     370} 
     371 
     372tFrameworkElement* tFrameworkElement::GetDescendant(const tPath& path, uint path_index, tFrameworkElement& root) 
     373{ 
    346374  if (IsDeleted()) 
    347375  { 
    348     return NULL; 
    349   } 
    350  
    351   if (name[name_index] == '/') 
    352   { 
    353     return root.GetChildElement(name, name_index + 1, only_globally_unique_children, root); 
    354   } 
    355  
    356   only_globally_unique_children &= (!GetFlag(tFlag::GLOBALLY_UNIQUE_LINK)); 
    357   for (auto it = children->Begin(); it != children->End(); ++it) 
    358   { 
    359     tLink* child = &(**it); 
    360     if (name.compare(name_index, child->name->length(), *(child->name)) == 0 && (!child->GetChild().IsDeleted())) 
    361     { 
    362       if (name.length() == name_index + child->name->length()) 
    363       { 
    364         if (!only_globally_unique_children || child->GetChild().GetFlag(tFlag::GLOBALLY_UNIQUE_LINK)) 
     376    return nullptr; 
     377  } 
     378  core::tFrameworkElement* current = path.IsAbsolute() ? &root : this; 
     379  while (current && path_index < path.Size()) 
     380  { 
     381    if (path[path_index] == ".") 
     382    { 
     383    } 
     384    else if (path[path_index] == "..") 
     385    { 
     386      current = current->GetParent(); 
     387    } 
     388    else 
     389    { 
     390      tFrameworkElement* temp = current; 
     391      current = nullptr; 
     392      for (auto it = temp->children->Begin(); it != temp->children->End(); ++it) 
     393      { 
     394        tLink* child = &(**it); 
     395        if (path[path_index] == (*child->name) && (!child->GetChild().IsDeleted())) 
    365396        { 
    366           return &child->GetChild(); 
     397          current = &child->GetChild(); 
     398          break; 
    367399        } 
    368400      } 
    369       if (name[name_index + child->name->length()] == '/') 
    370       { 
    371         tFrameworkElement* result = child->GetChild().GetChildElement(name, name_index + child->name->length() + 1, only_globally_unique_children, root); 
    372         if (result) 
    373         { 
    374           return result; 
    375         } 
    376         // continue, because links may contain '/'... (this is slightly ugly... better solution? TODO) 
    377       } 
    378     } 
    379   } 
    380   return NULL; 
    381 } 
    382  
    383 const tFrameworkElement::tLink* tFrameworkElement::GetLink(size_t link_index) const 
    384 { 
     401    } 
     402    path_index++; 
     403  } 
     404  return current; 
     405} 
     406 
     407const tFrameworkElement::tLink& tFrameworkElement::GetLink(size_t link_index) const 
     408{ 
     409  if (link_index == 0) 
     410  { 
     411    return primary; 
     412  } 
     413 
    385414  tLock lock(GetStructureMutex());  // absolutely safe this way 
    386415  if (IsDeleted()) 
    387416  { 
    388     return NULL; 
     417    return *cINVALID_LINK; 
    389418  } 
    390419  const tLink* l = &(primary); 
     
    392421  { 
    393422    l = l->next; 
    394     if (l == NULL) 
    395     { 
    396       return NULL; 
    397     } 
    398   } 
    399   return l; 
     423    if (!l) 
     424    { 
     425      return *cINVALID_LINK; 
     426    } 
     427  } 
     428  return *l; 
    400429} 
    401430 
     
    417446  if (IsDeleted()) 
    418447  { 
    419     return 0u; 
    420   } 
    421   size_t i = 0u; 
    422   for (const tLink* l = &(primary); l != NULL; l = l->next) 
     448    return 0; 
     449  } 
     450  size_t i = 0; 
     451  for (const tLink* l = &(primary); l != nullptr; l = l->next) 
    423452  { 
    424453    i++; 
     
    433462  { 
    434463    l = l->next; 
    435     if (l == NULL) 
    436     { 
    437       return NULL; 
     464    if (l == nullptr) 
     465    { 
     466      return nullptr; 
    438467    } 
    439468  } 
    440469  return l; 
    441 } 
    442  
    443 void tFrameworkElement::GetNameHelper(tString& sb, const tLink& l, bool abort_at_link_root) 
    444 { 
    445   if (l.parent == NULL || (abort_at_link_root && l.GetChild().GetFlag(tFlag::ALTERNATIVE_LINK_ROOT)))    // runtime? 
    446   { 
    447     return; 
    448   } 
    449   GetNameHelper(sb, l.parent->primary, abort_at_link_root); 
    450   sb.append("/"); 
    451   sb.append(*(l.name)); 
    452470} 
    453471 
     
    457475  if (IsDeleted()) 
    458476  { 
    459     return NULL; 
    460   } 
    461   return GetLink(link_index)->parent; 
     477    return nullptr; 
     478  } 
     479  return GetLink(link_index).parent; 
    462480} 
    463481 
    464482tFrameworkElement* tFrameworkElement::GetParentWithFlags(tFlags parent_flags) const 
    465483{ 
    466   if (primary.parent == NULL) 
    467   { 
    468     return NULL; 
     484  if (!primary.parent) 
     485  { 
     486    return nullptr; 
    469487  } 
    470488  tLock lock(GetStructureMutex());  // not really necessary after element has been initialized 
    471489  if (IsDeleted()) 
    472490  { 
    473     return NULL; 
     491    return nullptr; 
    474492  } 
    475493 
     
    478496  { 
    479497    result = result->primary.parent; 
    480     if (result == NULL || result->IsDeleted()) 
     498    if (result == nullptr || result->IsDeleted()) 
    481499    { 
    482500      break; 
     
    486504} 
    487505 
    488 bool tFrameworkElement::GetQualifiedName(tString& sb, const tLink& start, bool force_full_link) const 
    489 { 
     506bool tFrameworkElement::GetPath(tPath& result, const tLink& link) const 
     507{ 
     508  if (link.IsInvalid()) 
     509  { 
     510    result.Clear(); 
     511    return false; 
     512  } 
    490513  if (IsReady()) 
    491514  { 
    492     return GetQualifiedNameImpl(sb, start, force_full_link); 
     515    return GetPathImplementation(result, link); 
    493516  } 
    494517  else 
    495518  { 
    496519    tLock lock(GetStructureMutex());  // synchronize while element is under construction 
    497     return GetQualifiedNameImpl(sb, start, force_full_link); 
    498   } 
    499 } 
    500  
    501 bool tFrameworkElement::GetQualifiedNameImpl(tString& sb, const tLink& start, bool force_full_link) const 
    502 { 
    503   size_t length = 0u; 
    504   bool abort_at_link_root = false; 
    505   for (const tLink* l = &start; l->parent != NULL && !(abort_at_link_root && l->GetChild().GetFlag(tFlag::ALTERNATIVE_LINK_ROOT)); l = &(l->parent->primary)) 
    506   { 
    507     abort_at_link_root |= (!force_full_link) && l->GetChild().GetFlag(tFlag::GLOBALLY_UNIQUE_LINK); 
    508     if (abort_at_link_root && l->GetChild().GetFlag(tFlag::ALTERNATIVE_LINK_ROOT))    // if unique_link element is at the same time a link root 
    509     { 
    510       break; 
    511     } 
    512     length += l->name->length() + 1u; 
    513   } 
    514   sb.clear(); 
    515   if (sb.capacity() < length) 
    516   { 
    517     sb.reserve(length); 
    518   } 
    519  
    520   GetNameHelper(sb, start, abort_at_link_root); 
    521   assert(sb.length() == length); 
    522  
    523   // remove any characters if buffer is too long 
    524   //      if (len2 < sb.length()) { 
    525   //          sb.delete(len2, sb.length()); 
    526   //      } 
    527   return abort_at_link_root; 
     520    return GetPathImplementation(result, link); 
     521  } 
     522} 
     523 
     524bool tFrameworkElement::GetPathImplementation(tPath& result, const tLink& link) const 
     525{ 
     526  bool unique_result = link.GetChild().GetFlag(tFlag::GLOBALLY_UNIQUE_LINK); 
     527  size_t parent_count = internal::CountNumberOfAncestors(link); 
     528  rrlib::uri::tStringRange path_elements[parent_count + 1];  // +1 for this 
     529  rrlib::uri::tStringRange* path_element = &path_elements[parent_count]; 
     530  (*path_element) = link.GetName(); 
     531  path_element--; 
     532  core::tFrameworkElement* parent = link.GetParent(); 
     533  while (parent && (!parent->IsRuntime())) 
     534  { 
     535    (*path_element) = parent->GetName(); 
     536    unique_result |= parent->GetFlag(tFlag::GLOBALLY_UNIQUE_LINK); 
     537    path_element--; 
     538    parent = parent->GetParent(); 
     539  } 
     540  assert(path_element == path_elements - 1); 
     541  result.Set(true, path_elements, &path_elements[parent_count + 1]); 
     542  return unique_result; 
    528543} 
    529544 
    530545tRuntimeEnvironment& tFrameworkElement::GetRuntime() 
    531546{ 
    532   //return getParent(RuntimeEnvironment.class); 
    533547  return tRuntimeEnvironment::GetInstance(); 
    534548} 
     
    552566 
    553567  CheckPublish(); 
    554  
    555   /*for (@SizeT int i = 0, n = publishThese.size(); i < n; i++) { 
    556       publishThese.get(i).publishUpdatedInfo(RuntimeListener.ADD); 
    557   }*/ 
    558568} 
    559569 
     
    581591  if (init_this) 
    582592  { 
    583     PreChildInit(); 
    584593    GetRuntime().PreElementInit(*this); 
    585594    CheckForNameClash(primary); 
     
    617626  if (init_this) 
    618627  { 
    619     PostChildInit(); 
     628    OnInitialization(); 
    620629    { 
    621630      //tLock lock(*this); // we have structure lock 
     
    710719    FINROC_LOG_PRINT(DEBUG_VERBOSE_1, "Deleting"); 
    711720    assert(!GetFlag(tFlag::DELETED)); 
    712     assert(((primary.GetParent() != NULL) | GetFlag(tFlag::RUNTIME))); 
     721    assert(((primary.GetParent() != NULL) || IsRuntime())); 
    713722    tFlags new_flags = flags | tFlag::DELETED; 
    714723    new_flags.Set(tFlag::READY, false); 
     
    719728    flags = new_flags; 
    720729 
    721     if (!GetFlag(tFlag::RUNTIME)) 
     730    if (!IsRuntime()) 
    722731    { 
    723732      GetRuntime().UnregisterElement(*this); 
    724       //GetRuntime().MarkElementDeleted(*this); 
    725733    } 
    726734 
    727735    // perform custom cleanup (stopping/deleting threads can be done here) 
    728     PrepareDelete(); 
     736    OnManagedDelete(); 
    729737 
    730738    // remove children (thread-safe, because delete flag is set - and addChild etc. checks that) 
     
    735743 
    736744    // remove from hierarchy 
    737     for (tLink* l = &(primary); l != NULL;) 
    738     { 
    739       if (l != dont_detach && l->parent != NULL) 
     745    for (tLink* l = &(primary); l != nullptr;) 
     746    { 
     747      if (l != dont_detach && l->parent != nullptr) 
    740748      { 
    741749        l->parent->children->Remove(l); 
     
    744752    } 
    745753 
    746     primary.parent = NULL; 
     754    primary.parent = nullptr; 
    747755  } 
    748756 
     
    751759} 
    752760 
    753 bool tFrameworkElement::NameEquals(const tString& other) const 
    754 { 
    755   if (IsReady()) 
    756   { 
    757     return primary.name->compare(other) == 0; 
    758   } 
    759   else 
    760   { 
    761     tLock lock(GetStructureMutex()); 
    762     if (IsDeleted()) 
    763     { 
    764       return false; 
    765     } 
    766     return primary.name->compare(other) == 0; 
    767   } 
    768 } 
    769  
    770 void tFrameworkElement::PrintStructure() const 
    771 { 
    772   std::stringstream ls; 
    773   ls << "" << std::endl; 
    774   PrintStructure(0, ls); 
    775   FINROC_LOG_PRINT(USER, ls.str()); 
    776 } 
    777  
    778 void tFrameworkElement::PrintStructure(int indent, std::stringstream& output) const 
    779 { 
    780   tLock lock(GetStructureMutex()); 
    781  
    782   // print element info 
    783   for (int i = 0; i < indent; i++) 
    784   { 
    785     output << " "; 
    786   } 
    787  
    788   if (IsDeleted()) 
    789   { 
    790     output << "deleted FrameworkElement" << std::endl; 
    791     return; 
    792   } 
    793  
    794   output << GetName() << " (" << (IsReady() ? (GetFlag(tFlag::PUBLISHED) ? "published" : "ready") : IsDeleted() ? "deleted" : "constructing") << ")" << std::endl; 
    795  
    796   // print child element info 
    797   for (auto it = ChildrenBegin(); it != ChildrenEnd(); ++it) 
    798   { 
    799     it->PrintStructure(indent + 2, output); 
    800   } 
    801 } 
    802  
    803 void tFrameworkElement::PublishUpdatedEdgeInfo(tRuntimeListener::tEvent change_type, tAbstractPort& target) 
    804 { 
    805   GetRuntime().RuntimeChange(change_type, *this, &target, !GetFlag(tFlag::PUBLISHED)); 
    806 } 
    807  
    808761void tFrameworkElement::PublishUpdatedInfo(tRuntimeListener::tEvent change_type) 
    809762{ 
    810763  if (change_type == tRuntimeListener::tEvent::ADD || GetFlag(tFlag::PUBLISHED)) 
    811764  { 
    812     GetRuntime().RuntimeChange(change_type, *this, NULL); 
     765    GetRuntime().RuntimeChange(change_type, *this); 
    813766  } 
    814767} 
     
    816769void tFrameworkElement::SetFlag(tFlag flag, bool value) 
    817770{ 
    818   assert(flag >= tFlag::READY); 
     771  assert(flag >= tFlag::READY || (IsPort() && flag == tFlag::HIJACKED_PORT)); 
    819772  flags.Set(flag, value); 
    820773} 
     
    827780    return; 
    828781  } 
    829   if (GetFlag(tFlag::RUNTIME)) 
     782  if (IsRuntime()) 
    830783  { 
    831784    FINROC_LOG_PRINT(ERROR, "May not be called on Finroc Runtime Root Element. Ignoring."); 
     
    858811    primary.name = &(string_buffer_annotation->string_buffer); 
    859812  } 
    860  
    861813} 
    862814 
     
    865817  name(&cUNNAMED_ELEMENT_STRING), 
    866818  name_buffer(), 
    867   parent(NULL), 
    868   next(NULL) 
     819  parent(nullptr), 
     820  next(nullptr) 
    869821{} 
    870822 
     
    926878static void StreamQualifiedName(std::ostream& output, const tFrameworkElement& fe, bool first) 
    927879{ 
    928   if (!fe.GetFlag(tFrameworkElement::tFlag::RUNTIME)) 
     880  if (!fe.IsRuntime()) 
    929881  { 
    930882    if (fe.GetParent()) 
     
    943895{ 
    944896  StreamQualifiedName(output, fe, true); 
    945   output << " (" << ((void*)&fe) << ")"; 
     897  //output << " (" << ((void*)&fe) << ")"; 
    946898  return output; 
    947899} 
Note: See TracChangeset for help on using the changeset viewer.