|
16 | 16 | */
|
17 | 17 |
|
18 | 18 | #include <list>
|
| 19 | +#include <mutex> |
19 | 20 | #include <set>
|
| 21 | +#include <unordered_set> |
20 | 22 |
|
21 | 23 | #include <gz/common/StringUtils.hh>
|
22 | 24 |
|
| 25 | +#include "SystemInternal.hh" |
23 | 26 | #include "gz/sim/components/SystemPluginInfo.hh"
|
24 | 27 | #include "gz/sim/Conversions.hh"
|
25 | 28 | #include "SystemManager.hh"
|
@@ -122,7 +125,9 @@ size_t SystemManager::ActivatePendingSystems()
|
122 | 125 | this->systemsUpdate.push_back(system.update);
|
123 | 126 |
|
124 | 127 | if (system.postupdate)
|
| 128 | + { |
125 | 129 | this->systemsPostupdate.push_back(system.postupdate);
|
| 130 | + } |
126 | 131 | }
|
127 | 132 |
|
128 | 133 | this->pendingSystems.clear();
|
@@ -409,3 +414,131 @@ void SystemManager::ProcessPendingEntitySystems()
|
409 | 414 | }
|
410 | 415 | this->systemsToAdd.clear();
|
411 | 416 | }
|
| 417 | + |
| 418 | +template <typename T> |
| 419 | +struct identity |
| 420 | +{ |
| 421 | + using type = T; |
| 422 | +}; |
| 423 | + |
| 424 | +////////////////////////////////////////////////// |
| 425 | +/// TODO(arjo) - When we move to C++20 we can just use erase_if |
| 426 | +/// Removes all items that match the given predicate. |
| 427 | +/// This function runs in O(n) time and uses memory in-place |
| 428 | +template<typename Tp> |
| 429 | +void RemoveFromVectorIf(std::vector<Tp>& vec, |
| 430 | + typename identity<std::function<bool(const Tp&)>>::type pred) |
| 431 | +{ |
| 432 | + vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end()); |
| 433 | +} |
| 434 | + |
| 435 | +////////////////////////////////////////////////// |
| 436 | +void SystemManager::ProcessRemovedEntities( |
| 437 | + const EntityComponentManager &_ecm, |
| 438 | + bool &_needsCleanUp) |
| 439 | +{ |
| 440 | + // Note: This function has O(n) time when an entity is removed |
| 441 | + // where n is number of systems. Ideally we would only iterate |
| 442 | + // over entities marked for removal but that would involve having |
| 443 | + // a key value map. This can be marked as a future improvement. |
| 444 | + if (!_ecm.HasEntitiesMarkedForRemoval()) |
| 445 | + { |
| 446 | + return; |
| 447 | + } |
| 448 | + |
| 449 | + std::unordered_set<ISystemReset *> resetSystemsToBeRemoved; |
| 450 | + std::unordered_set<ISystemPreUpdate *> preupdateSystemsToBeRemoved; |
| 451 | + std::unordered_set<ISystemUpdate *> updateSystemsToBeRemoved; |
| 452 | + std::unordered_set<ISystemPostUpdate *> postupdateSystemsToBeRemoved; |
| 453 | + std::unordered_set<ISystemConfigure *> configureSystemsToBeRemoved; |
| 454 | + std::unordered_set<ISystemConfigureParameters *> |
| 455 | + configureParametersSystemsToBeRemoved; |
| 456 | + for (const auto &system : this->systems) |
| 457 | + { |
| 458 | + if (_ecm.IsMarkedForRemoval(system.parentEntity)) |
| 459 | + { |
| 460 | + if (system.reset) |
| 461 | + { |
| 462 | + resetSystemsToBeRemoved.insert(system.reset); |
| 463 | + } |
| 464 | + if (system.preupdate) |
| 465 | + { |
| 466 | + preupdateSystemsToBeRemoved.insert(system.preupdate); |
| 467 | + } |
| 468 | + if (system.update) |
| 469 | + { |
| 470 | + updateSystemsToBeRemoved.insert(system.update); |
| 471 | + } |
| 472 | + if (system.postupdate) |
| 473 | + { |
| 474 | + postupdateSystemsToBeRemoved.insert(system.postupdate); |
| 475 | + // If system with a PostUpdate is marked for removal |
| 476 | + // mark all worker threads for removal. |
| 477 | + _needsCleanUp = true; |
| 478 | + } |
| 479 | + if (system.configure) |
| 480 | + { |
| 481 | + configureSystemsToBeRemoved.insert(system.configure); |
| 482 | + } |
| 483 | + if (system.configureParameters) |
| 484 | + { |
| 485 | + configureParametersSystemsToBeRemoved.insert( |
| 486 | + system.configureParameters); |
| 487 | + } |
| 488 | + } |
| 489 | + } |
| 490 | + |
| 491 | + RemoveFromVectorIf(this->systemsReset, |
| 492 | + [&](const auto system) { |
| 493 | + if (resetSystemsToBeRemoved.count(system)) { |
| 494 | + return true; |
| 495 | + } |
| 496 | + return false; |
| 497 | + }); |
| 498 | + RemoveFromVectorIf(this->systemsPreupdate, |
| 499 | + [&](const auto& system) { |
| 500 | + if (preupdateSystemsToBeRemoved.count(system)) { |
| 501 | + return true; |
| 502 | + } |
| 503 | + return false; |
| 504 | + }); |
| 505 | + RemoveFromVectorIf(this->systemsUpdate, |
| 506 | + [&](const auto& system) { |
| 507 | + if (updateSystemsToBeRemoved.count(system)) { |
| 508 | + return true; |
| 509 | + } |
| 510 | + return false; |
| 511 | + }); |
| 512 | + |
| 513 | + RemoveFromVectorIf(this->systemsPostupdate, |
| 514 | + [&](const auto& system) { |
| 515 | + if (postupdateSystemsToBeRemoved.count(system)) { |
| 516 | + return true; |
| 517 | + } |
| 518 | + return false; |
| 519 | + }); |
| 520 | + RemoveFromVectorIf(this->systemsConfigure, |
| 521 | + [&](const auto& system) { |
| 522 | + if (configureSystemsToBeRemoved.count(system)) { |
| 523 | + return true; |
| 524 | + } |
| 525 | + return false; |
| 526 | + }); |
| 527 | + RemoveFromVectorIf(this->systemsConfigureParameters, |
| 528 | + [&](const auto& system) { |
| 529 | + if (configureParametersSystemsToBeRemoved.count(system)) { |
| 530 | + return true; |
| 531 | + } |
| 532 | + return false; |
| 533 | + }); |
| 534 | + RemoveFromVectorIf(this->systems, |
| 535 | + [&](const SystemInternal& _arg) { |
| 536 | + return _ecm.IsMarkedForRemoval(_arg.parentEntity); |
| 537 | + }); |
| 538 | + |
| 539 | + std::lock_guard lock(this->pendingSystemsMutex); |
| 540 | + RemoveFromVectorIf(this->pendingSystems, |
| 541 | + [&](const SystemInternal& _system) { |
| 542 | + return _ecm.IsMarkedForRemoval(_system.parentEntity); |
| 543 | + }); |
| 544 | +} |
0 commit comments