|
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"
|
@@ -115,7 +118,9 @@ size_t SystemManager::ActivatePendingSystems()
|
115 | 118 | this->systemsUpdate.push_back(system.update);
|
116 | 119 |
|
117 | 120 | if (system.postupdate)
|
| 121 | + { |
118 | 122 | this->systemsPostupdate.push_back(system.postupdate);
|
| 123 | + } |
119 | 124 | }
|
120 | 125 |
|
121 | 126 | this->pendingSystems.clear();
|
@@ -318,3 +323,119 @@ void SystemManager::ProcessPendingEntitySystems()
|
318 | 323 | }
|
319 | 324 | this->systemsToAdd.clear();
|
320 | 325 | }
|
| 326 | + |
| 327 | +template <typename T> |
| 328 | +struct identity |
| 329 | +{ |
| 330 | + using type = T; |
| 331 | +}; |
| 332 | + |
| 333 | +////////////////////////////////////////////////// |
| 334 | +/// TODO(arjo) - When we move to C++20 we can just use erase_if |
| 335 | +/// Removes all items that match the given predicate. |
| 336 | +/// This function runs in O(n) time and uses memory in-place |
| 337 | +template<typename Tp> |
| 338 | +void RemoveFromVectorIf(std::vector<Tp>& vec, |
| 339 | + typename identity<std::function<bool(const Tp&)>>::type pred) |
| 340 | +{ |
| 341 | + vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end()); |
| 342 | +} |
| 343 | + |
| 344 | +////////////////////////////////////////////////// |
| 345 | +void SystemManager::ProcessRemovedEntities( |
| 346 | + const EntityComponentManager &_ecm, |
| 347 | + bool &_needsCleanUp) |
| 348 | +{ |
| 349 | + // Note: This function has O(n) time when an entity is removed |
| 350 | + // where n is number of systems. Ideally we would only iterate |
| 351 | + // over entities marked for removal but that would involve having |
| 352 | + // a key value map. This can be marked as a future improvement. |
| 353 | + if (!_ecm.HasEntitiesMarkedForRemoval()) |
| 354 | + { |
| 355 | + return; |
| 356 | + } |
| 357 | + |
| 358 | + std::unordered_set<ISystemPreUpdate *> preupdateSystemsToBeRemoved; |
| 359 | + std::unordered_set<ISystemUpdate *> updateSystemsToBeRemoved; |
| 360 | + std::unordered_set<ISystemPostUpdate *> postupdateSystemsToBeRemoved; |
| 361 | + std::unordered_set<ISystemConfigure *> configureSystemsToBeRemoved; |
| 362 | + std::unordered_set<ISystemConfigureParameters *> |
| 363 | + configureParametersSystemsToBeRemoved; |
| 364 | + for (const auto &system : this->systems) |
| 365 | + { |
| 366 | + if (_ecm.IsMarkedForRemoval(system.parentEntity)) |
| 367 | + { |
| 368 | + if (system.preupdate) |
| 369 | + { |
| 370 | + preupdateSystemsToBeRemoved.insert(system.preupdate); |
| 371 | + } |
| 372 | + if (system.update) |
| 373 | + { |
| 374 | + updateSystemsToBeRemoved.insert(system.update); |
| 375 | + } |
| 376 | + if (system.postupdate) |
| 377 | + { |
| 378 | + postupdateSystemsToBeRemoved.insert(system.postupdate); |
| 379 | + // If system with a PostUpdate is marked for removal |
| 380 | + // mark all worker threads for removal. |
| 381 | + _needsCleanUp = true; |
| 382 | + } |
| 383 | + if (system.configure) |
| 384 | + { |
| 385 | + configureSystemsToBeRemoved.insert(system.configure); |
| 386 | + } |
| 387 | + if (system.configureParameters) |
| 388 | + { |
| 389 | + configureParametersSystemsToBeRemoved.insert( |
| 390 | + system.configureParameters); |
| 391 | + } |
| 392 | + } |
| 393 | + } |
| 394 | + |
| 395 | + RemoveFromVectorIf(this->systemsPreupdate, |
| 396 | + [&](const auto& system) { |
| 397 | + if (preupdateSystemsToBeRemoved.count(system)) { |
| 398 | + return true; |
| 399 | + } |
| 400 | + return false; |
| 401 | + }); |
| 402 | + RemoveFromVectorIf(this->systemsUpdate, |
| 403 | + [&](const auto& system) { |
| 404 | + if (updateSystemsToBeRemoved.count(system)) { |
| 405 | + return true; |
| 406 | + } |
| 407 | + return false; |
| 408 | + }); |
| 409 | + |
| 410 | + RemoveFromVectorIf(this->systemsPostupdate, |
| 411 | + [&](const auto& system) { |
| 412 | + if (postupdateSystemsToBeRemoved.count(system)) { |
| 413 | + return true; |
| 414 | + } |
| 415 | + return false; |
| 416 | + }); |
| 417 | + RemoveFromVectorIf(this->systemsConfigure, |
| 418 | + [&](const auto& system) { |
| 419 | + if (configureSystemsToBeRemoved.count(system)) { |
| 420 | + return true; |
| 421 | + } |
| 422 | + return false; |
| 423 | + }); |
| 424 | + RemoveFromVectorIf(this->systemsConfigureParameters, |
| 425 | + [&](const auto& system) { |
| 426 | + if (configureParametersSystemsToBeRemoved.count(system)) { |
| 427 | + return true; |
| 428 | + } |
| 429 | + return false; |
| 430 | + }); |
| 431 | + RemoveFromVectorIf(this->systems, |
| 432 | + [&](const SystemInternal& _arg) { |
| 433 | + return _ecm.IsMarkedForRemoval(_arg.parentEntity); |
| 434 | + }); |
| 435 | + |
| 436 | + std::lock_guard lock(this->pendingSystemsMutex); |
| 437 | + RemoveFromVectorIf(this->pendingSystems, |
| 438 | + [&](const SystemInternal& _system) { |
| 439 | + return _ecm.IsMarkedForRemoval(_system.parentEntity); |
| 440 | + }); |
| 441 | +} |
0 commit comments