1212#include < cassert>
1313#include < atomic>
1414#include < memory>
15+ #include < shared_mutex>
1516#include < string>
1617
1718// Entity-Component System
@@ -604,14 +605,17 @@ namespace wi::ecs
604605 };
605606 Item items[64 ];
606607 };
608+ mutable std::shared_mutex mutex;
607609 wi::unordered_map<uint64_t , Block> table;
608610
609611 inline void clear ()
610612 {
613+ std::unique_lock lock (mutex);
611614 table.clear ();
612615 }
613616 inline void erase (Entity entity)
614617 {
618+ std::unique_lock lock (mutex);
615619 const uint64_t block_index = entity >> 6ull ; // entity / 64
616620 auto it = table.find (block_index);
617621 if (it == table.end ())
@@ -631,6 +635,7 @@ namespace wi::ecs
631635 }
632636 inline void insert (Entity entity, size_t index)
633637 {
638+ std::unique_lock lock (mutex);
634639 const uint64_t block_index = entity >> 6ull ; // entity / 64
635640 const uint64_t item_index = entity & 63ull ; // entity % 64
636641 Block& block = table[block_index];
@@ -639,6 +644,7 @@ namespace wi::ecs
639644 }
640645 inline size_t get (Entity entity) const
641646 {
647+ std::shared_lock lock (mutex);
642648 const uint64_t block_index = entity >> 6ull ; // entity / 64
643649 const auto it = table.find (block_index);
644650 if (it == table.end ())
@@ -653,21 +659,25 @@ namespace wi::ecs
653659 // Implementation with hash table:
654660 // The standard hashing method, performance depends on hashing, hash collisions
655661 wi::unordered_map<Entity, size_t > table;
656-
662+ mutable std::shared_mutex mutex;
657663 inline void clear ()
658664 {
665+ std::unique_lock lock (mutex);
659666 table.clear ();
660667 }
661668 inline void erase (Entity entity)
662669 {
670+ std::unique_lock lock (mutex);
663671 table.erase (entity);
664672 }
665673 inline void insert (Entity entity, size_t index)
666674 {
675+ std::unique_lock lock (mutex);
667676 table[entity] = index;
668677 }
669678 inline size_t get (Entity entity) const
670679 {
680+ std::shared_lock lock (mutex);
671681 if (table.empty ())
672682 return INVALID_INDEX ;
673683 auto it = table.find (entity);
@@ -694,13 +704,15 @@ namespace wi::ecs
694704 uint64_t version = 0 ;
695705 };
696706 wi::unordered_map<std::string, LibraryEntry> entries;
707+ mutable std::shared_mutex mutex;
697708
698709 // Create an instance of ComponentManager of a certain data type
699710 // The name must be unique, it will be used in serialization
700711 // version is optional, it will be propagated to ComponentManager::Serialize() inside the EntitySerializer parameter
701712 template <typename T>
702713 inline ComponentManager<T>& Register (const std::string& name, uint64_t version = 0 )
703714 {
715+ std::unique_lock lock (mutex);
704716 entries[name].component_manager = std::make_unique<ComponentManager<T>>();
705717 entries[name].version = version;
706718 return static_cast <ComponentManager<T>&>(*entries[name].component_manager );
@@ -709,6 +721,7 @@ namespace wi::ecs
709721 template <typename T>
710722 inline ComponentManager<T>* Get (const std::string& name)
711723 {
724+ std::shared_lock lock (mutex);
712725 auto it = entries.find (name);
713726 if (it == entries.end ())
714727 return nullptr ;
@@ -718,6 +731,7 @@ namespace wi::ecs
718731 template <typename T>
719732 inline const ComponentManager<T>* Get (const std::string& name) const
720733 {
734+ std::shared_lock lock (mutex);
721735 auto it = entries.find (name);
722736 if (it == entries.end ())
723737 return nullptr ;
@@ -726,6 +740,7 @@ namespace wi::ecs
726740
727741 inline uint64_t GetVersion (std::string name) const
728742 {
743+ std::shared_lock lock (mutex);
729744 auto it = entries.find (name);
730745 if (it == entries.end ())
731746 return 0 ;
0 commit comments