libultraship
Reimplementations of libultra (N64 SDK) functions for modern hardware
Loading...
Searching...
No Matches
PartList.h
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4#include <vector>
5#include <memory>
6#include <type_traits>
7#include <algorithm>
8#include <mutex>
9#include <stdint.h>
10
11#include "ship/core/Part.h"
12
13namespace Ship {
14
22enum class ListReturnCode : int32_t {
23 ForcedSuccess = 2,
24 Success = 1,
25 Duplicate = 0,
26 NoItemsProvided = -1,
27 NotPermitted = -2,
28 NotFound = -3,
29 Failed = -4
30};
31
32template <typename C, typename StoredPtr> struct PartListStoredPtrTraits;
33
40template <typename C> struct PartListStoredPtrTraits<C, std::shared_ptr<C>> {
46 static std::shared_ptr<C> Lock(const std::shared_ptr<C>& ptr) {
47 return ptr;
48 }
49
55 static bool IsExpired(const std::shared_ptr<C>& ptr) {
56 return ptr == nullptr;
57 }
58
64 static std::shared_ptr<C> Store(const std::shared_ptr<C>& ptr) {
65 return ptr;
66 }
67};
68
75template <typename C> struct PartListStoredPtrTraits<C, std::weak_ptr<C>> {
81 static std::shared_ptr<C> Lock(const std::weak_ptr<C>& ptr) {
82 return ptr.lock();
83 }
84
90 static bool IsExpired(const std::weak_ptr<C>& ptr) {
91 return ptr.expired();
92 }
93
99 static std::weak_ptr<C> Store(const std::shared_ptr<C>& ptr) {
100 return ptr;
101 }
102};
103
114template <typename C = Part, typename StoredPtr = std::shared_ptr<C>> class PartList : public Part {
115 public:
116 static_assert(std::is_same<StoredPtr, std::shared_ptr<C>>::value ||
117 std::is_same<StoredPtr, std::weak_ptr<C>>::value,
118 "StoredPtr must be std::shared_ptr<C> or std::weak_ptr<C>");
119
124 explicit PartList(const size_t initialAllocation = 0);
125 virtual ~PartList() = default;
126
132 bool Has(std::shared_ptr<C> part) const;
133
139 template <typename T> bool Has() const;
140
146 bool Has(const uint64_t id) const;
147
149 bool Has() const;
150
152 size_t GetCount() const;
153
160 uint64_t GetMutationVersion() const {
161 return mMutationVersion;
162 }
163
169 std::shared_ptr<C> Get(const uint64_t id) const;
170
172 std::shared_ptr<std::vector<std::shared_ptr<C>>> Get() const;
173
179 template <typename T> std::shared_ptr<std::vector<std::shared_ptr<T>>> Get() const;
180
186 std::shared_ptr<std::vector<std::shared_ptr<C>>> Get(const std::vector<uint64_t>& ids) const;
187
193 template <typename T> std::shared_ptr<T> GetFirst() const;
194
201 ListReturnCode Add(std::shared_ptr<C> part, const bool force = false);
202
209 ListReturnCode Add(const std::vector<std::shared_ptr<C>>& parts, const bool force = false);
210
217 ListReturnCode Remove(std::shared_ptr<C> part, const bool force = false);
218
225 ListReturnCode Remove(const uint64_t id, const bool force = false);
226
232 ListReturnCode Remove(const bool force = false);
233
240 ListReturnCode Remove(const std::vector<std::shared_ptr<C>>& parts, const bool force = false);
241
248 template <typename T> ListReturnCode Remove(const bool force = false);
249
256 ListReturnCode Remove(const std::vector<uint64_t>& ids, const bool force = false);
257
258 protected:
264 template <typename P = StoredPtr>
265 typename std::enable_if<std::is_same<P, std::shared_ptr<C>>::value, std::vector<P>&>::type GetList();
266
272 template <typename P = StoredPtr>
273 typename std::enable_if<std::is_same<P, std::shared_ptr<C>>::value, const std::vector<P>&>::type GetList() const;
274
275#ifdef COMPONENT_THREAD_SAFE
277 std::recursive_mutex& GetMutex() const;
278#endif
279
290 virtual bool CanAdd(std::shared_ptr<C> part);
291
302 virtual bool CanRemove(std::shared_ptr<C> part);
303
309 virtual void Added(std::shared_ptr<C> part, const bool forced);
310
316 virtual void Removed(std::shared_ptr<C> part, const bool forced);
317
318 private:
320
321 std::shared_ptr<C> LockPtr(const StoredPtr& ptr) const;
322 StoredPtr StorePtr(const std::shared_ptr<C>& ptr) const;
323 bool IsExpiredPtr(const StoredPtr& ptr) const;
324 void PruneExpired();
325 bool ContainsIdUnlocked(const uint64_t id) const;
326 bool EraseByIdUnlocked(const uint64_t id, std::shared_ptr<C>* removedPart = nullptr);
327
328 std::vector<StoredPtr> mList;
329 uint64_t mMutationVersion = 0;
330#ifdef COMPONENT_THREAD_SAFE
331 mutable std::recursive_mutex mMutex;
332#endif
333};
334
335// ---- Inline implementations ----
336
337template <typename C, typename StoredPtr>
338PartList<C, StoredPtr>::PartList(const size_t initialAllocation)
339 : Part(), mList()
340#ifdef COMPONENT_THREAD_SAFE
341 ,
342 mMutex()
343#endif
344{
345 mList.reserve(initialAllocation);
346}
347
348template <typename C, typename StoredPtr>
349std::shared_ptr<C> PartList<C, StoredPtr>::LockPtr(const StoredPtr& ptr) const {
350 return PtrTraits::Lock(ptr);
351}
352
353template <typename C, typename StoredPtr>
354StoredPtr PartList<C, StoredPtr>::StorePtr(const std::shared_ptr<C>& ptr) const {
355 return PtrTraits::Store(ptr);
356}
357
358template <typename C, typename StoredPtr> bool PartList<C, StoredPtr>::IsExpiredPtr(const StoredPtr& ptr) const {
359 return PtrTraits::IsExpired(ptr);
360}
361
362template <typename C, typename StoredPtr> void PartList<C, StoredPtr>::PruneExpired() {
363 const auto oldSize = mList.size();
364 mList.erase(std::remove_if(mList.begin(), mList.end(), [this](const StoredPtr& ptr) { return IsExpiredPtr(ptr); }),
365 mList.end());
366 if (mList.size() != oldSize) {
367 ++mMutationVersion;
368 }
369}
370
371template <typename C, typename StoredPtr> bool PartList<C, StoredPtr>::ContainsIdUnlocked(const uint64_t id) const {
372 return std::find_if(mList.begin(), mList.end(), [this, id](const StoredPtr& item) {
373 auto locked = LockPtr(item);
374 return locked && locked->GetId() == id;
375 }) != mList.end();
376}
377
378template <typename C, typename StoredPtr>
379bool PartList<C, StoredPtr>::EraseByIdUnlocked(const uint64_t id, std::shared_ptr<C>* removedPart) {
380 auto it = std::find_if(mList.begin(), mList.end(), [this, id](const StoredPtr& item) {
381 auto locked = LockPtr(item);
382 return locked && locked->GetId() == id;
383 });
384
385 if (it == mList.end()) {
386 return false;
387 }
388
389 if (removedPart != nullptr) {
390 *removedPart = LockPtr(*it);
391 }
392
393 mList.erase(it);
394 ++mMutationVersion;
395 return true;
396}
397
398template <typename C, typename StoredPtr>
399ListReturnCode PartList<C, StoredPtr>::Add(std::shared_ptr<C> part, const bool force) {
400 if (!part) {
402 }
403
404 const bool canAdd = CanAdd(part);
405 if (!canAdd && !force) {
407 }
408
409 const bool forced = !canAdd && force;
410 const uint64_t id = part->GetId();
411
412 {
413#ifdef COMPONENT_THREAD_SAFE
414 const std::lock_guard<std::recursive_mutex> lock(mMutex);
415#endif
416 PruneExpired();
417 if (ContainsIdUnlocked(id)) {
419 }
420 mList.push_back(StorePtr(part));
421 ++mMutationVersion;
422 }
423
424 bool shouldRunHooks = false;
425 {
426#ifdef COMPONENT_THREAD_SAFE
427 const std::lock_guard<std::recursive_mutex> lock(mMutex);
428#endif
429 shouldRunHooks = ContainsIdUnlocked(id);
430 }
431
432 if (!shouldRunHooks) {
434 }
435
436 try {
437 Added(part, forced);
438 part->OnAdded(forced);
439 } catch (...) {
440#ifdef COMPONENT_THREAD_SAFE
441 const std::lock_guard<std::recursive_mutex> lock(mMutex);
442#endif
443 PruneExpired();
444 EraseByIdUnlocked(id);
446 }
447
449}
450
451template <typename C, typename StoredPtr>
452ListReturnCode PartList<C, StoredPtr>::Add(const std::vector<std::shared_ptr<C>>& parts, const bool force) {
453 if (parts.empty()) {
455 }
456
458 for (const auto& part : parts) {
459 const ListReturnCode r = Add(part, force);
460 if (static_cast<int32_t>(r) > static_cast<int32_t>(result)) {
461 result = r;
462 } else if (static_cast<int32_t>(r) < static_cast<int32_t>(ListReturnCode::Duplicate) &&
463 static_cast<int32_t>(r) < static_cast<int32_t>(result)) {
464 result = r;
465 }
466 }
467 return result;
468}
469
470template <typename C, typename StoredPtr>
471ListReturnCode PartList<C, StoredPtr>::Remove(std::shared_ptr<C> part, const bool force) {
472 if (!part) {
474 }
475
476 const bool canRemove = CanRemove(part);
477 if (!canRemove && !force) {
479 }
480
481 const bool forced = !canRemove && force;
482 const uint64_t id = part->GetId();
483 std::shared_ptr<C> removedPart = nullptr;
484
485 {
486#ifdef COMPONENT_THREAD_SAFE
487 const std::lock_guard<std::recursive_mutex> lock(mMutex);
488#endif
489 PruneExpired();
490 if (!EraseByIdUnlocked(id, &removedPart)) {
492 }
493 }
494
495 if (!removedPart) {
497 }
498
499 bool shouldRunHooks = false;
500 {
501#ifdef COMPONENT_THREAD_SAFE
502 const std::lock_guard<std::recursive_mutex> lock(mMutex);
503#endif
504 shouldRunHooks = !ContainsIdUnlocked(id);
505 }
506
507 if (!shouldRunHooks) {
509 }
510
511 try {
512 Removed(removedPart, forced);
513 removedPart->OnRemoved(forced);
514 } catch (...) {
515#ifdef COMPONENT_THREAD_SAFE
516 const std::lock_guard<std::recursive_mutex> lock(mMutex);
517#endif
518 PruneExpired();
519 if (!ContainsIdUnlocked(id)) {
520 mList.push_back(StorePtr(removedPart));
521 ++mMutationVersion;
522 }
524 }
525
527}
528
529template <typename C, typename StoredPtr>
530ListReturnCode PartList<C, StoredPtr>::Remove(const uint64_t id, const bool force) {
531 std::shared_ptr<C> candidate = nullptr;
532 {
533#ifdef COMPONENT_THREAD_SAFE
534 const std::lock_guard<std::recursive_mutex> lock(mMutex);
535#endif
536 PruneExpired();
537 if (!ContainsIdUnlocked(id)) {
539 }
540 auto found = std::find_if(mList.begin(), mList.end(), [this, id](const StoredPtr& item) {
541 auto locked = LockPtr(item);
542 return locked && locked->GetId() == id;
543 });
544 candidate = found != mList.end() ? LockPtr(*found) : nullptr;
545 }
546
547 if (!candidate) {
549 }
550
551 const bool canRemove = CanRemove(candidate);
552 if (!canRemove && !force) {
554 }
555
556 const bool forced = !canRemove && force;
557 std::shared_ptr<C> removedPart = nullptr;
558
559 {
560#ifdef COMPONENT_THREAD_SAFE
561 const std::lock_guard<std::recursive_mutex> lock(mMutex);
562#endif
563 PruneExpired();
564 if (!EraseByIdUnlocked(id, &removedPart)) {
566 }
567 }
568
569 if (!removedPart) {
571 }
572
573 bool shouldRunHooks = false;
574 {
575#ifdef COMPONENT_THREAD_SAFE
576 const std::lock_guard<std::recursive_mutex> lock(mMutex);
577#endif
578 shouldRunHooks = !ContainsIdUnlocked(id);
579 }
580
581 if (!shouldRunHooks) {
583 }
584
585 try {
586 Removed(removedPart, forced);
587 removedPart->OnRemoved(forced);
588 } catch (...) {
589#ifdef COMPONENT_THREAD_SAFE
590 const std::lock_guard<std::recursive_mutex> lock(mMutex);
591#endif
592 PruneExpired();
593 if (!ContainsIdUnlocked(id)) {
594 mList.push_back(StorePtr(removedPart));
595 ++mMutationVersion;
596 }
598 }
599
601}
602
603template <typename C, typename StoredPtr> ListReturnCode PartList<C, StoredPtr>::Remove(const bool force) {
604 std::vector<std::shared_ptr<C>> snapshot;
605 {
606#ifdef COMPONENT_THREAD_SAFE
607 const std::lock_guard<std::recursive_mutex> lock(mMutex);
608#endif
609 PruneExpired();
610 if (mList.empty()) {
612 }
613
614 snapshot.reserve(mList.size());
615 for (const auto& item : mList) {
616 auto locked = LockPtr(item);
617 if (locked) {
618 snapshot.push_back(locked);
619 }
620 }
621 }
622
624 for (const auto& part : snapshot) {
625 const ListReturnCode r = Remove(part, force);
626 if (static_cast<int32_t>(r) > static_cast<int32_t>(result)) {
627 result = r;
628 } else if (static_cast<int32_t>(r) < static_cast<int32_t>(ListReturnCode::Duplicate) &&
629 static_cast<int32_t>(r) < static_cast<int32_t>(result)) {
630 result = r;
631 }
632 }
633 return result;
634}
635
636template <typename C, typename StoredPtr>
637ListReturnCode PartList<C, StoredPtr>::Remove(const std::vector<std::shared_ptr<C>>& parts, const bool force) {
638 if (parts.empty()) {
640 }
641
643 for (const auto& part : parts) {
644 const ListReturnCode r = Remove(part, force);
645 if (static_cast<int32_t>(r) > static_cast<int32_t>(result)) {
646 result = r;
647 } else if (static_cast<int32_t>(r) < static_cast<int32_t>(ListReturnCode::Duplicate) &&
648 static_cast<int32_t>(r) < static_cast<int32_t>(result)) {
649 result = r;
650 }
651 }
652 return result;
653}
654
655template <typename C, typename StoredPtr>
656template <typename T>
658 std::vector<std::shared_ptr<C>> snapshot;
659 {
660#ifdef COMPONENT_THREAD_SAFE
661 const std::lock_guard<std::recursive_mutex> lock(mMutex);
662#endif
663 PruneExpired();
664
665 snapshot.reserve(mList.size());
666 for (const auto& item : mList) {
667 auto locked = LockPtr(item);
668 if (locked && std::dynamic_pointer_cast<T>(locked) != nullptr) {
669 snapshot.push_back(locked);
670 }
671 }
672 }
673
674 if (snapshot.empty()) {
676 }
677
679 for (const auto& part : snapshot) {
680 const ListReturnCode r = Remove(part, force);
681 if (static_cast<int32_t>(r) > static_cast<int32_t>(result)) {
682 result = r;
683 } else if (static_cast<int32_t>(r) < static_cast<int32_t>(ListReturnCode::Duplicate) &&
684 static_cast<int32_t>(r) < static_cast<int32_t>(result)) {
685 result = r;
686 }
687 }
688 return result;
689}
690
691template <typename C, typename StoredPtr>
692ListReturnCode PartList<C, StoredPtr>::Remove(const std::vector<uint64_t>& ids, const bool force) {
693 if (ids.empty()) {
695 }
696
697 std::vector<std::shared_ptr<C>> snapshot;
698 {
699#ifdef COMPONENT_THREAD_SAFE
700 const std::lock_guard<std::recursive_mutex> lock(mMutex);
701#endif
702 PruneExpired();
703
704 snapshot.reserve(mList.size());
705 for (const auto& item : mList) {
706 auto locked = LockPtr(item);
707 if (locked && std::find(ids.begin(), ids.end(), locked->GetId()) != ids.end()) {
708 snapshot.push_back(locked);
709 }
710 }
711 }
712
713 if (snapshot.empty()) {
715 }
716
718 for (const auto& part : snapshot) {
719 const ListReturnCode r = Remove(part, force);
720 if (static_cast<int32_t>(r) > static_cast<int32_t>(result)) {
721 result = r;
722 } else if (static_cast<int32_t>(r) < static_cast<int32_t>(ListReturnCode::Duplicate) &&
723 static_cast<int32_t>(r) < static_cast<int32_t>(result)) {
724 result = r;
725 }
726 }
727 return result;
728}
729
730template <typename C, typename StoredPtr>
731template <typename P>
732typename std::enable_if<std::is_same<P, std::shared_ptr<C>>::value, std::vector<P>&>::type
734 return mList;
735}
736
737template <typename C, typename StoredPtr>
738template <typename P>
739typename std::enable_if<std::is_same<P, std::shared_ptr<C>>::value, const std::vector<P>&>::type
741 return mList;
742}
743
744#ifdef COMPONENT_THREAD_SAFE
745template <typename C, typename StoredPtr> std::recursive_mutex& PartList<C, StoredPtr>::GetMutex() const {
746 return mMutex;
747}
748#endif
749
750template <typename C, typename StoredPtr> bool PartList<C, StoredPtr>::CanAdd(std::shared_ptr<C> part) {
751 return true;
752}
753
754template <typename C, typename StoredPtr> bool PartList<C, StoredPtr>::CanRemove(std::shared_ptr<C> part) {
755 return true;
756}
757
758template <typename C, typename StoredPtr>
759void PartList<C, StoredPtr>::Added(std::shared_ptr<C> part, const bool forced) {
760}
761
762template <typename C, typename StoredPtr>
763void PartList<C, StoredPtr>::Removed(std::shared_ptr<C> part, const bool forced) {
764}
765
766template <typename C, typename StoredPtr> bool PartList<C, StoredPtr>::Has(std::shared_ptr<C> part) const {
767 if (!part) {
768 return false;
769 }
770#ifdef COMPONENT_THREAD_SAFE
771 const std::lock_guard<std::recursive_mutex> lock(mMutex);
772#endif
773 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
774 return ContainsIdUnlocked(part->GetId());
775}
776
777template <typename C, typename StoredPtr> template <typename T> bool PartList<C, StoredPtr>::Has() const {
778#ifdef COMPONENT_THREAD_SAFE
779 const std::lock_guard<std::recursive_mutex> lock(mMutex);
780#endif
781 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
782 return std::find_if(mList.begin(), mList.end(), [this](const StoredPtr& item) {
783 auto locked = LockPtr(item);
784 return locked && std::dynamic_pointer_cast<T>(locked) != nullptr;
785 }) != mList.end();
786}
787
788template <typename C, typename StoredPtr> bool PartList<C, StoredPtr>::Has(const uint64_t id) const {
789#ifdef COMPONENT_THREAD_SAFE
790 const std::lock_guard<std::recursive_mutex> lock(mMutex);
791#endif
792 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
793 return ContainsIdUnlocked(id);
794}
795
796template <typename C, typename StoredPtr> bool PartList<C, StoredPtr>::Has() const {
797#ifdef COMPONENT_THREAD_SAFE
798 const std::lock_guard<std::recursive_mutex> lock(mMutex);
799#endif
800 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
801 return !mList.empty();
802}
803
804template <typename C, typename StoredPtr> size_t PartList<C, StoredPtr>::GetCount() const {
805#ifdef COMPONENT_THREAD_SAFE
806 const std::lock_guard<std::recursive_mutex> lock(mMutex);
807#endif
808 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
809 return mList.size();
810}
811
812template <typename C, typename StoredPtr> std::shared_ptr<C> PartList<C, StoredPtr>::Get(const uint64_t id) const {
813#ifdef COMPONENT_THREAD_SAFE
814 const std::lock_guard<std::recursive_mutex> lock(mMutex);
815#endif
816 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
817 auto it = std::find_if(mList.begin(), mList.end(), [this, id](const StoredPtr& item) {
818 auto locked = LockPtr(item);
819 return locked && locked->GetId() == id;
820 });
821 return it != mList.end() ? LockPtr(*it) : nullptr;
822}
823
824template <typename C, typename StoredPtr>
825std::shared_ptr<std::vector<std::shared_ptr<C>>> PartList<C, StoredPtr>::Get() const {
826#ifdef COMPONENT_THREAD_SAFE
827 const std::lock_guard<std::recursive_mutex> lock(mMutex);
828#endif
829 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
830 auto result = std::make_shared<std::vector<std::shared_ptr<C>>>();
831 result->reserve(mList.size());
832 for (const auto& item : mList) {
833 auto locked = LockPtr(item);
834 if (locked) {
835 result->push_back(locked);
836 }
837 }
838 return result;
839}
840
841template <typename C, typename StoredPtr>
842template <typename T>
843std::shared_ptr<std::vector<std::shared_ptr<T>>> PartList<C, StoredPtr>::Get() const {
844#ifdef COMPONENT_THREAD_SAFE
845 const std::lock_guard<std::recursive_mutex> lock(mMutex);
846#endif
847 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
848 auto result = std::make_shared<std::vector<std::shared_ptr<T>>>();
849 for (const auto& item : mList) {
850 auto locked = LockPtr(item);
851 if (!locked) {
852 continue;
853 }
854 auto typed = std::dynamic_pointer_cast<T>(locked);
855 if (typed) {
856 result->push_back(typed);
857 }
858 }
859 return result;
860}
861
862template <typename C, typename StoredPtr>
863template <typename T>
864std::shared_ptr<T> PartList<C, StoredPtr>::GetFirst() const {
865#ifdef COMPONENT_THREAD_SAFE
866 const std::lock_guard<std::recursive_mutex> lock(mMutex);
867#endif
868 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
869 for (const auto& item : mList) {
870 auto locked = LockPtr(item);
871 if (!locked) {
872 continue;
873 }
874 auto typed = std::dynamic_pointer_cast<T>(locked);
875 if (typed) {
876 return typed;
877 }
878 }
879 return nullptr;
880}
881
882template <typename C, typename StoredPtr>
883std::shared_ptr<std::vector<std::shared_ptr<C>>> PartList<C, StoredPtr>::Get(const std::vector<uint64_t>& ids) const {
884#ifdef COMPONENT_THREAD_SAFE
885 const std::lock_guard<std::recursive_mutex> lock(mMutex);
886#endif
887 const_cast<PartList<C, StoredPtr>*>(this)->PruneExpired();
888 auto result = std::make_shared<std::vector<std::shared_ptr<C>>>();
889 for (const auto& item : mList) {
890 auto locked = LockPtr(item);
891 if (!locked) {
892 continue;
893 }
894 if (std::find(ids.begin(), ids.end(), locked->GetId()) != ids.end()) {
895 result->push_back(locked);
896 }
897 }
898 return result;
899}
900
901} // namespace Ship
A thread-safe ordered list of Parts.
Definition PartList.h:114
PartList(const size_t initialAllocation=0)
Constructs a PartList, optionally pre-allocating storage.
Definition PartList.h:338
ListReturnCode Remove(std::shared_ptr< C > part, const bool force=false)
Removes a specific Part from the list.
Definition PartList.h:471
ListReturnCode Remove(const bool force=false)
Removes all Parts that can be dynamic_cast to type T.
Definition PartList.h:657
bool Has() const
Checks whether any Part of type T is in the list.
Definition PartList.h:777
ListReturnCode Remove(const uint64_t id, const bool force=false)
Removes a Part by its unique ID.
Definition PartList.h:530
std::recursive_mutex & GetMutex() const
Returns the internal recursive mutex used to guard list access.
Definition PartList.h:745
std::shared_ptr< std::vector< std::shared_ptr< C > > > Get(const std::vector< uint64_t > &ids) const
Returns all Parts whose IDs appear in the given vector.
Definition PartList.h:883
size_t GetCount() const
Returns the number of currently live Parts in the list.
Definition PartList.h:804
bool Has() const
Checks whether the list contains any Parts at all.
Definition PartList.h:796
std::shared_ptr< std::vector< std::shared_ptr< C > > > Get() const
Returns a snapshot (copy) of all currently live Parts in the list.
Definition PartList.h:825
ListReturnCode Remove(const std::vector< uint64_t > &ids, const bool force=false)
Removes all Parts whose IDs appear in the given vector.
Definition PartList.h:692
virtual void Added(std::shared_ptr< C > part, const bool forced)
Notification hook called after a Part has been added.
Definition PartList.h:759
std::shared_ptr< std::vector< std::shared_ptr< T > > > Get() const
Returns all Parts that can be dynamic_cast to type T.
Definition PartList.h:843
ListReturnCode Add(const std::vector< std::shared_ptr< C > > &parts, const bool force=false)
Adds multiple Parts to the list.
Definition PartList.h:452
virtual void Removed(std::shared_ptr< C > part, const bool forced)
Notification hook called after a Part has been removed.
Definition PartList.h:763
uint64_t GetMutationVersion() const
Returns a monotonically increasing counter that increments on every add or remove.
Definition PartList.h:160
bool Has(std::shared_ptr< C > part) const
Checks whether a specific Part is in the list.
Definition PartList.h:766
ListReturnCode Remove(const std::vector< std::shared_ptr< C > > &parts, const bool force=false)
Removes multiple Parts from the list.
Definition PartList.h:637
virtual ~PartList()=default
ListReturnCode Remove(const bool force=false)
Removes all Parts from the list.
Definition PartList.h:603
virtual bool CanAdd(std::shared_ptr< C > part)
Permission hook called before adding a Part. Override to deny.
Definition PartList.h:750
ListReturnCode Add(std::shared_ptr< C > part, const bool force=false)
Adds a Part to the list if not already present.
Definition PartList.h:399
virtual bool CanRemove(std::shared_ptr< C > part)
Permission hook called before removing a Part. Override to deny.
Definition PartList.h:754
std::enable_if< std::is_same< P, std::shared_ptr< C > >::value, conststd::vector< P > & >::type GetList() const
Direct const access to the underlying vector for strong-storage lists.
Definition PartList.h:740
std::enable_if< std::is_same< P, std::shared_ptr< C > >::value, std::vector< P > & >::type GetList()
Direct access to the underlying vector for strong-storage lists.
Definition PartList.h:733
std::shared_ptr< C > Get(const uint64_t id) const
Retrieves a Part by its unique ID.
Definition PartList.h:812
std::shared_ptr< T > GetFirst() const
Returns the first Part that can be dynamic_cast to T.
Definition PartList.h:864
bool Has(const uint64_t id) const
Checks whether a Part with the given ID is in the list.
Definition PartList.h:788
Base class for all identifiable objects in the component system.
Definition Part.h:27
friend class PartList
Definition Part.h:86
Core namespace for the libultraship engine framework.
Definition gfx_direct3d_common.h:14
ListReturnCode
Return codes for PartList add/remove operations.
Definition PartList.h:22
@ ForcedSuccess
Operation succeeded via force override.
@ NotFound
The specified Part was not found.
@ Success
Operation succeeded normally.
@ NoItemsProvided
The input collection was empty.
@ NotPermitted
Operation blocked by a permission check.
@ Failed
General failure (e.g. null pointer).
@ Duplicate
Part already present; list unchanged.
static std::shared_ptr< C > Store(const std::shared_ptr< C > &ptr)
Converts an API pointer into strong stored form.
Definition PartList.h:64
static bool IsExpired(const std::shared_ptr< C > &ptr)
Indicates whether the stored pointer is considered expired.
Definition PartList.h:55
static std::shared_ptr< C > Lock(const std::shared_ptr< C > &ptr)
Returns the stored pointer unchanged.
Definition PartList.h:46
static std::weak_ptr< C > Store(const std::shared_ptr< C > &ptr)
Converts an API pointer into weak stored form.
Definition PartList.h:99
static bool IsExpired(const std::weak_ptr< C > &ptr)
Indicates whether the weak pointer is expired.
Definition PartList.h:90
static std::shared_ptr< C > Lock(const std::weak_ptr< C > &ptr)
Locks a weak pointer.
Definition PartList.h:81
Definition PartList.h:32