9#define EC_INIT_ENTITIES_SIZE 256 
   10#define EC_GROW_SIZE_AMOUNT 256 
   25#include <unordered_map> 
   26#include <unordered_set> 
   35#include "Meta/Combine.hpp" 
   36#include "Meta/ForEachDoubleTuple.hpp" 
   37#include "Meta/ForEachWithIndex.hpp" 
   38#include "Meta/IndexOf.hpp" 
   39#include "Meta/Matching.hpp" 
   40#include "ThreadPool.hpp" 
   68template <
typename ComponentsList, 
typename TagsList,
 
   69          unsigned int ThreadCount = 4>
 
   72    using Components = ComponentsList;
 
   73    using Tags = TagsList;
 
   74    using Combined = EC::Meta::Combine<ComponentsList, TagsList>;
 
   78    using ComponentsTuple = EC::Meta::Morph<ComponentsList, std::tuple<> >;
 
   79    static_assert(std::is_default_constructible<ComponentsTuple>::value,
 
   80                  "All components must be default constructible");
 
   82    template <
typename... Types>
 
   84        using type = std::tuple<std::deque<Types>..., std::deque<char> >;
 
   86    using ComponentsStorage =
 
   87        typename EC::Meta::Morph<ComponentsList, Storage<> >::type;
 
   90    using EntitiesTupleType = std::tuple<bool, BitsetType>;
 
   91    using EntitiesType = std::deque<EntitiesTupleType>;
 
   93    EntitiesType entities;
 
   94    ComponentsStorage componentsStorage;
 
   95    std::size_t currentCapacity = 0;
 
   96    std::size_t currentSize = 0;
 
   97    std::unordered_set<std::size_t> deletedSet;
 
   99    std::unique_ptr<ThreadPool<ThreadCount> > threadPool;
 
  101    std::atomic_uint deferringDeletions;
 
  102    std::vector<std::size_t> deferredDeletions;
 
  103    std::mutex deferredDeletionsMutex;
 
  105    std::vector<std::size_t> idStack;
 
  106    std::size_t idStackCounter;
 
  107    std::mutex idStackMutex;
 
  113        std::array<std::size_t, 2> range;
 
  115        EntitiesType* entities;
 
  118        std::unordered_set<std::size_t> dead;
 
 
  121    template <
typename Function>
 
  123        std::array<std::size_t, 2> range;
 
  125        EntitiesType* entities;
 
  129        std::unordered_set<std::size_t> dead;
 
 
  133        std::array<std::size_t, 2> range;
 
  135        EntitiesType* entities;
 
  137        const std::vector<std::size_t>* matching;
 
  138        std::unordered_set<std::size_t> dead;
 
 
  142        std::array<std::size_t, 2> range;
 
  144        std::vector<std::vector<std::size_t> >* matchingV;
 
  145        const std::vector<BitsetType*>* bitsets;
 
  146        EntitiesType* entities;
 
  148        std::unordered_set<std::size_t> dead;
 
 
  152        std::array<std::size_t, 2> range;
 
  154        std::vector<std::vector<std::size_t> >* multiMatchingEntities;
 
  157        std::unordered_set<std::size_t> dead;
 
 
  161        std::array<std::size_t, 2> range;
 
  165        std::vector<std::vector<std::size_t> >* multiMatchingEntities;
 
  166        std::unordered_set<std::size_t> dead;
 
 
  170        std::array<std::size_t, 2> range;
 
  172        std::vector<std::vector<std::size_t> >* multiMatchingEntities;
 
  175        std::unordered_set<std::size_t> dead;
 
 
  178    template <
typename Iterable>
 
  180        std::array<std::size_t, 2> range;
 
  182        EntitiesType* entities;
 
  185        std::unordered_set<std::size_t> dead;
 
 
  196        resize(EC_INIT_ENTITIES_SIZE);
 
  197        if (ThreadCount >= 2) {
 
  198            threadPool = std::make_unique<ThreadPool<ThreadCount> >();
 
  201        deferringDeletions.store(0);
 
 
  206            while (!threadPool->isNotRunning()) {
 
  207                std::this_thread::sleep_for(std::chrono::microseconds(30));
 
  213    void resize(std::size_t newCapacity) {
 
  214        if (currentCapacity >= newCapacity) {
 
  218        EC::Meta::forEach<ComponentsList>([
this, newCapacity](
auto t) {
 
  219            std::get<std::deque<
decltype(t)> >(this->componentsStorage)
 
  220                .resize(newCapacity);
 
  223        entities.resize(newCapacity);
 
  224        for (std::size_t i = currentCapacity; i < newCapacity; ++i) {
 
  225            entities[i] = std::make_tuple(
false, BitsetType{});
 
  228        currentCapacity = newCapacity;
 
  238        if (deletedSet.empty()) {
 
  239            if (currentSize == currentCapacity) {
 
  240                resize(currentCapacity + EC_GROW_SIZE_AMOUNT);
 
  243            std::get<bool>(entities[currentSize]) = 
true;
 
  245            return currentSize++;
 
  249                auto iter = deletedSet.begin();
 
  251                deletedSet.erase(iter);
 
  253            std::get<bool>(entities[
id]) = 
true;
 
 
  259    void deleteEntityImpl(std::size_t 
id) {
 
  261            std::get<bool>(entities.at(
id)) = 
false;
 
  262            std::get<BitsetType>(entities.at(
id)).reset();
 
  263            deletedSet.insert(
id);
 
  276        if (deferringDeletions.load() != 0) {
 
  277            std::lock_guard<std::mutex> lock(deferredDeletionsMutex);
 
  278            deferredDeletions.push_back(index);
 
  280            deleteEntityImpl(index);
 
 
  285    void handleDeferredDeletions() {
 
  286        if (deferringDeletions.fetch_sub(1) == 1) {
 
  287            std::lock_guard<std::mutex> lock(deferredDeletionsMutex);
 
  288            for (std::size_t 
id : deferredDeletions) {
 
  289                deleteEntityImpl(
id);
 
  291            deferredDeletions.clear();
 
  303        return index < currentSize;
 
 
  312    bool isAlive(
const std::size_t& index)
 const {
 
  313        return hasEntity(index) && std::get<bool>(entities.at(index));
 
 
  323        return currentSize - deletedSet.size();
 
 
  333    std::size_t getCurrentCapacity()
 const { 
return currentCapacity; }
 
  345        return entities.at(index);
 
 
  361    template <
typename Component>
 
  363        constexpr auto componentIndex =
 
  365        if (componentIndex < Components::size) {
 
  369            return (Component*)&std::get<componentIndex>(componentsStorage)
 
 
  391    template <
typename Component>
 
  409    template <
typename Component>
 
  411        constexpr auto componentIndex =
 
  413        if (componentIndex < Components::size) {
 
  417            return (Component*)&std::get<componentIndex>(componentsStorage)
 
 
  439    template <
typename Component>
 
  453    template <
typename Component>
 
  455        return std::get<BitsetType>(entities.at(index))
 
  456            .template getComponentBit<Component>();
 
 
  467    template <
typename Tag>
 
  468    bool hasTag(
const std::size_t& index)
 const {
 
  469        return std::get<BitsetType>(entities.at(index))
 
  470            .template getTagBit<Tag>();
 
 
  502    template <
typename Component, 
typename... Args>
 
  504        if (!EC::Meta::Contains<Component, Components>::value ||
 
  509        Component component(std::forward<Args>(args)...);
 
  511        std::get<BitsetType>(entities[entityID])
 
  512            .template getComponentBit<Component>() = 
true;
 
  519        (*((std::deque<Component>*)(&std::get<index>(
 
  520            componentsStorage))))[entityID] = std::move(component);
 
 
  534    template <
typename Component>
 
  536        if (!EC::Meta::Contains<Component, Components>::value ||
 
  541        std::get<BitsetType>(entities[entityID])
 
  542            .template getComponentBit<Component>() = 
false;
 
 
  553    template <
typename Tag>
 
  554    void addTag(
const std::size_t& entityID) {
 
  555        if (!EC::Meta::Contains<Tag, Tags>::value || !
isAlive(entityID)) {
 
  559        std::get<BitsetType>(entities[entityID]).template getTagBit<Tag>() =
 
 
  573    template <
typename Tag>
 
  575        if (!EC::Meta::Contains<Tag, Tags>::value || !
isAlive(entityID)) {
 
  579        std::get<BitsetType>(entities[entityID]).template getTagBit<Tag>() =
 
 
  596        resize(EC_INIT_ENTITIES_SIZE);
 
  598        std::lock_guard<std::mutex> lock(deferredDeletionsMutex);
 
  599        deferringDeletions.store(0);
 
  600        deferredDeletions.clear();
 
 
  604    template <
typename... Types>
 
  605    struct ForMatchingSignatureHelper {
 
  606        template <
typename CType, 
typename Function>
 
  607        static void call(
const std::size_t& entityID, CType& ctype,
 
  608                         Function&& function, 
void* userData = 
nullptr) {
 
  609            function(entityID, userData,
 
  613        template <
typename CType, 
typename Function>
 
  614        static void callPtr(
const std::size_t& entityID, CType& ctype,
 
  615                            Function* function, 
void* userData = 
nullptr) {
 
  616            (*function)(entityID, userData,
 
  620        template <
typename CType, 
typename Function>
 
  621        void callInstance(
const std::size_t& entityID, CType& ctype,
 
  622                          Function&& function, 
void* userData = 
nullptr)
 const {
 
  623            ForMatchingSignatureHelper<Types...>::call(
 
  624                entityID, ctype, std::forward<Function>(function), userData);
 
  627        template <
typename CType, 
typename Function>
 
  628        void callInstancePtr(
const std::size_t& entityID, CType& ctype,
 
  630                             void* userData = 
nullptr)
 const {
 
  631            ForMatchingSignatureHelper<Types...>::callPtr(entityID, ctype,
 
  676    template <
typename Signature, 
typename Function>
 
  678                              const bool useThreadPool = 
false) {
 
  679        std::size_t current_id;
 
  682            std::lock_guard<std::mutex> lock(idStackMutex);
 
  683            current_id = idStackCounter++;
 
  684            idStack.push_back(current_id);
 
  686        deferringDeletions.fetch_add(1);
 
  687        using SignatureComponents =
 
  690            EC::Meta::Morph<SignatureComponents, ForMatchingSignatureHelper<> >;
 
  693            BitsetType::template generateBitset<Signature>();
 
  694        if (!useThreadPool || !threadPool) {
 
  695            for (std::size_t i = 0; i < currentSize; ++i) {
 
  696                if (!std::get<bool>(entities[i])) {
 
  700                if ((signatureBitset & std::get<BitsetType>(entities[i])) ==
 
  702                    Helper::call(i, *
this, std::forward<Function>(function),
 
  707            std::array<TPFnDataStructZero, ThreadCount * 2> fnDataAr;
 
  709            std::size_t s = currentSize / (ThreadCount * 2);
 
  710            for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
  711                std::size_t begin = s * i;
 
  713                if (i == ThreadCount * 2 - 1) {
 
  721                fnDataAr[i].range = {begin, end};
 
  722                fnDataAr[i].manager = 
this;
 
  723                fnDataAr[i].entities = &entities;
 
  724                fnDataAr[i].signature = &signatureBitset;
 
  725                fnDataAr[i].userData = userData;
 
  726                for (std::size_t j = begin; j < end; ++j) {
 
  728                        fnDataAr[i].dead.insert(j);
 
  733                    [&function](
void* ud) {
 
  735                        for (std::size_t i = data->range[0]; i < data->range[1];
 
  737                            if (data->dead.find(i) != data->dead.end()) {
 
  741                            if (((*data->signature) &
 
  742                                 std::get<BitsetType>(data->entities->at(i))) ==
 
  744                                Helper::call(i, *data->manager,
 
  745                                             std::forward<Function>(function),
 
  752            threadPool->easyStartAndWait();
 
  758                std::lock_guard<std::mutex> lock(idStackMutex);
 
  759                if (idStack.back() == current_id) {
 
  764            std::this_thread::sleep_for(std::chrono::microseconds(15));
 
  767        handleDeferredDeletions();
 
 
  811    template <
typename Signature, 
typename Function>
 
  813                                 const bool useThreadPool = 
false) {
 
  814        std::size_t current_id;
 
  817            std::lock_guard<std::mutex> lock(idStackMutex);
 
  818            current_id = idStackCounter++;
 
  819            idStack.push_back(current_id);
 
  821        deferringDeletions.fetch_add(1);
 
  822        using SignatureComponents =
 
  825            EC::Meta::Morph<SignatureComponents, ForMatchingSignatureHelper<> >;
 
  828            BitsetType::template generateBitset<Signature>();
 
  829        if (!useThreadPool || !threadPool) {
 
  830            for (std::size_t i = 0; i < currentSize; ++i) {
 
  831                if (!std::get<bool>(entities[i])) {
 
  835                if ((signatureBitset & std::get<BitsetType>(entities[i])) ==
 
  837                    Helper::callPtr(i, *
this, function, userData);
 
  841            std::array<TPFnDataStructOne<Function>, ThreadCount * 2> fnDataAr;
 
  843            std::size_t s = currentSize / (ThreadCount * 2);
 
  844            for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
  845                std::size_t begin = s * i;
 
  847                if (i == ThreadCount * 2 - 1) {
 
  855                fnDataAr[i].range = {begin, end};
 
  856                fnDataAr[i].manager = 
this;
 
  857                fnDataAr[i].entities = &entities;
 
  858                fnDataAr[i].signature = &signatureBitset;
 
  859                fnDataAr[i].userData = userData;
 
  860                fnDataAr[i].fn = function;
 
  861                for (std::size_t j = begin; j < end; ++j) {
 
  863                        fnDataAr[i].dead.insert(j);
 
  870                        for (std::size_t i = data->range[0]; i < data->range[1];
 
  872                            if (data->dead.find(i) != data->dead.end()) {
 
  876                            if (((*data->signature) &
 
  877                                 std::get<BitsetType>(data->entities->at(i))) ==
 
  879                                Helper::callPtr(i, *data->manager, data->fn,
 
  886            threadPool->easyStartAndWait();
 
  892                std::lock_guard<std::mutex> lock(idStackMutex);
 
  893                if (idStack.back() == current_id) {
 
  898            std::this_thread::sleep_for(std::chrono::microseconds(15));
 
  901        handleDeferredDeletions();
 
 
  905    std::map<std::size_t,
 
  906             std::tuple<BitsetType, 
void*,
 
  907                        std::function<void(std::size_t,
 
  908                                           std::vector<std::size_t>, 
void*)> > >
 
  909        forMatchingFunctions;
 
  910    std::size_t functionIndex = 0;
 
  956    template <
typename Signature, 
typename Function>
 
  958                                       void* userData = 
nullptr) {
 
  959        deferringDeletions.fetch_add(1);
 
  960        while (forMatchingFunctions.find(functionIndex) !=
 
  961               forMatchingFunctions.end()) {
 
  965        using SignatureComponents =
 
  968            EC::Meta::Morph<SignatureComponents, ForMatchingSignatureHelper<> >;
 
  972            BitsetType::template generateBitset<Signature>();
 
  974        forMatchingFunctions.emplace(std::make_pair(
 
  977                signatureBitset, userData,
 
  978                [function, helper, 
this](
const bool useThreadPool,
 
  979                                         std::vector<std::size_t> matching,
 
  981                    if (!useThreadPool || !threadPool) {
 
  982                        for (
auto eid : matching) {
 
  984                                helper.callInstancePtr(eid, *
this, &function,
 
  989                        std::array<TPFnDataStructTwo, ThreadCount * 2> fnDataAr;
 
  991                        std::size_t s = matching.size() / (ThreadCount * 2);
 
  992                        for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
  993                            std::size_t begin = s * i;
 
  995                            if (i == ThreadCount * 2 - 1) {
 
  996                                end = matching.size();
 
 1003                            fnDataAr[i].range = {begin, end};
 
 1004                            fnDataAr[i].manager = 
this;
 
 1005                            fnDataAr[i].entities = &entities;
 
 1006                            fnDataAr[i].userData = userData;
 
 1007                            fnDataAr[i].matching = &matching;
 
 1008                            for (std::size_t j = begin; j < end; ++j) {
 
 1009                                if (!
isAlive(matching.at(j))) {
 
 1010                                    fnDataAr[i].dead.insert(j);
 
 1013                            threadPool->queueFn(
 
 1014                                [&function, helper](
void* ud) {
 
 1017                                    for (std::size_t i = data->range[0];
 
 1018                                         i < data->range[1]; ++i) {
 
 1019                                        if (data->dead.find(i) ==
 
 1021                                            helper.callInstancePtr(
 
 1022                                                data->matching->at(i),
 
 1023                                                *data->manager, &function,
 
 1030                        threadPool->easyStartAndWait();
 
 1034        handleDeferredDeletions();
 
 1035        return functionIndex++;
 
 
 1039    std::vector<std::vector<std::size_t> > getMatchingEntities(
 
 1040        std::vector<BitsetType*> bitsets, 
const bool useThreadPool = 
false) {
 
 1041        std::vector<std::vector<std::size_t> > matchingV(bitsets.size());
 
 1043        if (!useThreadPool || !threadPool) {
 
 1044            for (std::size_t i = 0; i < currentSize; ++i) {
 
 1048                for (std::size_t j = 0; j < bitsets.size(); ++j) {
 
 1049                    if (((*bitsets[j]) & std::get<BitsetType>(entities[i])) ==
 
 1051                        matchingV[j].push_back(i);
 
 1056            std::array<TPFnDataStructThree, ThreadCount * 2> fnDataAr;
 
 1058            std::size_t s = currentSize / (ThreadCount * 2);
 
 1060            for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
 1061                std::size_t begin = s * i;
 
 1063                if (i == ThreadCount * 2 - 1) {
 
 1071                fnDataAr[i].range = {begin, end};
 
 1072                fnDataAr[i].manager = 
this;
 
 1073                fnDataAr[i].matchingV = &matchingV;
 
 1074                fnDataAr[i].bitsets = &bitsets;
 
 1075                fnDataAr[i].entities = &entities;
 
 1076                fnDataAr[i].mutex = &mutex;
 
 1077                for (std::size_t j = begin; j < end; ++j) {
 
 1079                        fnDataAr[i].dead.insert(j);
 
 1082                threadPool->queueFn(
 
 1084                        auto* data = 
static_cast<TPFnDataStructThree*
>(ud);
 
 1085                        for (std::size_t i = data->range[0]; i < data->range[1];
 
 1087                            if (data->dead.find(i) != data->dead.end()) {
 
 1090                            for (std::size_t j = 0; j < data->bitsets->size();
 
 1092                                if ((*data->bitsets->at(j) &
 
 1093                                     std::get<BitsetType>(data->entities->at(
 
 1094                                         i))) == *data->bitsets->at(j)) {
 
 1095                                    std::lock_guard<std::mutex> lock(
 
 1097                                    data->matchingV->at(j).push_back(i);
 
 1104            threadPool->easyStartAndWait();
 
 1143        deferringDeletions.fetch_add(1);
 
 1144        std::vector<BitsetType*> bitsets;
 
 1145        for (
auto iter = forMatchingFunctions.begin();
 
 1146             iter != forMatchingFunctions.end(); ++iter) {
 
 1147            bitsets.push_back(&std::get<BitsetType>(iter->second));
 
 1150        std::vector<std::vector<std::size_t> > matching =
 
 1151            getMatchingEntities(bitsets, useThreadPool);
 
 1154        for (
auto iter = forMatchingFunctions.begin();
 
 1155             iter != forMatchingFunctions.end(); ++iter) {
 
 1156            std::get<2>(iter->second)(useThreadPool, matching[i++],
 
 1157                                      std::get<1>(iter->second));
 
 1160        handleDeferredDeletions();
 
 
 1193                                 const bool useThreadPool = 
false) {
 
 1194        auto iter = forMatchingFunctions.find(
id);
 
 1195        if (iter == forMatchingFunctions.end()) {
 
 1198        deferringDeletions.fetch_add(1);
 
 1199        std::vector<std::vector<std::size_t> > matching = getMatchingEntities(
 
 1200            std::vector<BitsetType*>{&std::get<BitsetType>(iter->second)},
 
 1202        std::get<2>(iter->second)(useThreadPool, matching[0],
 
 1203                                  std::get<1>(iter->second));
 
 1205        handleDeferredDeletions();
 
 
 1232        forMatchingFunctions.clear();
 
 
 1242        return forMatchingFunctions.erase(
id) == 1;
 
 
 1254    template <
typename List>
 
 1256        std::size_t deletedCount = 0;
 
 1257        for (
auto iter = forMatchingFunctions.begin();
 
 1258             iter != forMatchingFunctions.end();) {
 
 1259            if (std::find(list.begin(), list.end(), iter->first) ==
 
 1261                iter = forMatchingFunctions.erase(iter);
 
 1268        return deletedCount;
 
 
 1280        std::initializer_list<std::size_t> list) {
 
 
 1293    template <
typename List>
 
 1295        std::size_t deletedCount = 0;
 
 1296        for (
auto listIter = list.begin(); listIter != list.end(); ++listIter) {
 
 1297            deletedCount += forMatchingFunctions.erase(*listIter);
 
 1300        return deletedCount;
 
 
 1312        std::initializer_list<std::size_t> list) {
 
 
 1322        auto f = forMatchingFunctions.find(
id);
 
 1323        if (f != forMatchingFunctions.end()) {
 
 1324            std::get<1>(f->second) = userData;
 
 
 1378    template <
typename SigList, 
typename FTuple>
 
 1380                               const bool useThreadPool = 
false) {
 
 1381        std::size_t current_id;
 
 1384            std::lock_guard<std::mutex> lock(idStackMutex);
 
 1385            current_id = idStackCounter++;
 
 1386            idStack.push_back(current_id);
 
 1388        deferringDeletions.fetch_add(1);
 
 1389        std::vector<std::vector<std::size_t> > multiMatchingEntities(
 
 1394        EC::Meta::forEachWithIndex<SigList>(
 
 1395            [&signatureBitsets](
auto signature, 
const auto index) {
 
 1396                signatureBitsets[index] =
 
 1397                    BitsetType::template generateBitset<decltype(signature)>();
 
 1401        if (!useThreadPool || !threadPool) {
 
 1402            for (std::size_t eid = 0; eid < currentSize; ++eid) {
 
 1406                for (std::size_t i = 0; i < SigList::size; ++i) {
 
 1407                    if ((signatureBitsets[i] &
 
 1408                         std::get<BitsetType>(entities[eid])) ==
 
 1409                        signatureBitsets[i]) {
 
 1410                        multiMatchingEntities[i].push_back(eid);
 
 1415            std::array<TPFnDataStructFour, ThreadCount * 2> fnDataAr;
 
 1418            std::size_t s = currentSize / (ThreadCount * 2);
 
 1419            for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
 1420                std::size_t begin = s * i;
 
 1422                if (i == ThreadCount * 2 - 1) {
 
 1430                fnDataAr[i].range = {begin, end};
 
 1431                fnDataAr[i].manager = 
this;
 
 1432                fnDataAr[i].multiMatchingEntities = &multiMatchingEntities;
 
 1433                fnDataAr[i].signatures = signatureBitsets;
 
 1434                fnDataAr[i].mutex = &mutex;
 
 1435                for (std::size_t j = begin; j < end; ++j) {
 
 1437                        fnDataAr[i].dead.insert(j);
 
 1441                threadPool->queueFn(
 
 1444                        for (std::size_t i = data->range[0]; i < data->range[1];
 
 1446                            if (data->dead.find(i) != data->dead.end()) {
 
 1449                            for (std::size_t j = 0; j < SigList::size; ++j) {
 
 1450                                if ((data->signatures[j] &
 
 1451                                     std::get<BitsetType>(
 
 1452                                         data->manager->entities[i])) ==
 
 1453                                    data->signatures[j]) {
 
 1454                                    std::lock_guard<std::mutex> lock(
 
 1456                                    data->multiMatchingEntities->at(j)
 
 1464            threadPool->easyStartAndWait();
 
 1468        EC::Meta::forEachDoubleTuple(
 
 1469            EC::Meta::Morph<SigList, std::tuple<> >{}, fTuple,
 
 1470            [
this, &multiMatchingEntities, useThreadPool, &userData](
 
 1471                auto sig, 
auto func, 
auto index) {
 
 1472                using SignatureComponents =
 
 1474                                                ComponentsList>::type;
 
 1475                using Helper = EC::Meta::Morph<SignatureComponents,
 
 1476                                               ForMatchingSignatureHelper<> >;
 
 1477                if (!useThreadPool || !threadPool) {
 
 1478                    for (
const auto& 
id : multiMatchingEntities[index]) {
 
 1480                            Helper::call(
id, *
this, func, userData);
 
 1484                    std::array<TPFnDataStructFive, ThreadCount * 2> fnDataAr;
 
 1486                        multiMatchingEntities[index].size() / (ThreadCount * 2);
 
 1487                    for (
unsigned int i = 0; i < ThreadCount * 2; ++i) {
 
 1488                        std::size_t begin = s * i;
 
 1490                        if (i == ThreadCount * 2 - 1) {
 
 1491                            end = multiMatchingEntities[index].size();
 
 1498                        fnDataAr[i].range = {begin, end};
 
 1499                        fnDataAr[i].index = index;
 
 1500                        fnDataAr[i].manager = 
this;
 
 1501                        fnDataAr[i].userData = userData;
 
 1502                        fnDataAr[i].multiMatchingEntities =
 
 1503                            &multiMatchingEntities;
 
 1504                        for (std::size_t j = begin; j < end; ++j) {
 
 1506                                    multiMatchingEntities.at(index).at(j))) {
 
 1507                                fnDataAr[i].dead.insert(j);
 
 1510                        threadPool->queueFn(
 
 1514                                for (std::size_t i = data->range[0];
 
 1515                                     i < data->range[1]; ++i) {
 
 1516                                    if (data->dead.find(i) ==
 
 1518                                        Helper::call(data->multiMatchingEntities
 
 1521                                                     *data->manager, func,
 
 1528                    threadPool->easyStartAndWait();
 
 1535                std::lock_guard<std::mutex> lock(idStackMutex);
 
 1536                if (idStack.back() == current_id) {
 
 1541            std::this_thread::sleep_for(std::chrono::microseconds(15));
 
 1544        handleDeferredDeletions();
 
 
 1598    template <
typename SigList, 
typename FTuple>
 
 1600                                  const bool useThreadPool = 
false) {
 
 1601        std::size_t current_id;
 
 1604            std::lock_guard<std::mutex> lock(idStackMutex);
 
 1605            current_id = idStackCounter++;
 
 1606            idStack.push_back(current_id);
 
 1608        deferringDeletions.fetch_add(1);
 
 1609        std::vector<std::vector<std::size_t> > multiMatchingEntities(
 
 1614        EC::Meta::forEachWithIndex<SigList>(
 
 1615            [&signatureBitsets](
auto signature, 
const auto index) {
 
 1616                signatureBitsets[index] =
 
 1617                    BitsetType::template generateBitset<decltype(signature)>();
 
 1621        if (!useThreadPool || !threadPool) {
 
 1622            for (std::size_t eid = 0; eid < currentSize; ++eid) {
 
 1626                for (std::size_t i = 0; i < SigList::size; ++i) {
 
 1627                    if ((signatureBitsets[i] &
 
 1628                         std::get<BitsetType>(entities[eid])) ==
 
 1629                        signatureBitsets[i]) {
 
 1630                        multiMatchingEntities[i].push_back(eid);
 
 1635            std::array<TPFnDataStructSix, ThreadCount * 2> fnDataAr;
 
 1638            std::size_t s = currentSize / (ThreadCount * 2);
 
 1639            for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
 1640                std::size_t begin = s * i;
 
 1642                if (i == ThreadCount * 2 - 1) {
 
 1650                fnDataAr[i].range = {begin, end};
 
 1651                fnDataAr[i].manager = 
this;
 
 1652                fnDataAr[i].multiMatchingEntities = &multiMatchingEntities;
 
 1653                fnDataAr[i].bitsets = signatureBitsets;
 
 1654                fnDataAr[i].mutex = &mutex;
 
 1655                for (std::size_t j = begin; j < end; ++j) {
 
 1657                        fnDataAr[i].dead.insert(j);
 
 1661                threadPool->queueFn(
 
 1664                        for (std::size_t i = data->range[0]; i < data->range[1];
 
 1666                            if (data->dead.find(i) != data->dead.end()) {
 
 1669                            for (std::size_t j = 0; j < SigList::size; ++j) {
 
 1670                                if ((data->bitsets[j] &
 
 1671                                     std::get<BitsetType>(
 
 1672                                         data->manager->entities[i])) ==
 
 1674                                    std::lock_guard<std::mutex> lock(
 
 1676                                    data->multiMatchingEntities->at(j)
 
 1684            threadPool->easyStartAndWait();
 
 1688        EC::Meta::forEachDoubleTuple(
 
 1689            EC::Meta::Morph<SigList, std::tuple<> >{}, fTuple,
 
 1690            [
this, &multiMatchingEntities, useThreadPool, &userData](
 
 1691                auto sig, 
auto func, 
auto index) {
 
 1692                using SignatureComponents =
 
 1694                                                ComponentsList>::type;
 
 1695                using Helper = EC::Meta::Morph<SignatureComponents,
 
 1696                                               ForMatchingSignatureHelper<> >;
 
 1697                if (!useThreadPool || !threadPool) {
 
 1698                    for (
const auto& 
id : multiMatchingEntities[index]) {
 
 1700                            Helper::callPtr(
id, *
this, func, userData);
 
 1704                    std::array<TPFnDataStructFive, ThreadCount * 2> fnDataAr;
 
 1706                        multiMatchingEntities[index].size() / (ThreadCount * 2);
 
 1707                    for (
unsigned int i = 0; i < ThreadCount * 2; ++i) {
 
 1708                        std::size_t begin = s * i;
 
 1710                        if (i == ThreadCount * 2 - 1) {
 
 1711                            end = multiMatchingEntities[index].size();
 
 1718                        fnDataAr[i].range = {begin, end};
 
 1719                        fnDataAr[i].index = index;
 
 1720                        fnDataAr[i].manager = 
this;
 
 1721                        fnDataAr[i].userData = userData;
 
 1722                        fnDataAr[i].multiMatchingEntities =
 
 1723                            &multiMatchingEntities;
 
 1724                        for (std::size_t j = begin; j < end; ++j) {
 
 1726                                    multiMatchingEntities.at(index).at(j))) {
 
 1727                                fnDataAr[i].dead.insert(j);
 
 1730                        threadPool->queueFn(
 
 1734                                for (std::size_t i = data->range[0];
 
 1735                                     i < data->range[1]; ++i) {
 
 1736                                    if (data->dead.find(i) ==
 
 1739                                            data->multiMatchingEntities
 
 1742                                            *data->manager, func,
 
 1749                    threadPool->easyStartAndWait();
 
 1756                std::lock_guard<std::mutex> lock(idStackMutex);
 
 1757                if (idStack.back() == current_id) {
 
 1762            std::this_thread::sleep_for(std::chrono::microseconds(15));
 
 1765        handleDeferredDeletions();
 
 
 1788    template <
typename Signature>
 
 1790                           const bool useThreadPool = 
false) {
 
 1791        std::size_t current_id;
 
 1794            std::lock_guard<std::mutex> lock(idStackMutex);
 
 1795            current_id = idStackCounter++;
 
 1796            idStack.push_back(current_id);
 
 1798        deferringDeletions.fetch_add(1);
 
 1800            BitsetType::template generateBitset<Signature>();
 
 1801        if (!useThreadPool || !threadPool) {
 
 1802            for (std::size_t i = 0; i < currentSize; ++i) {
 
 1803                if (!std::get<bool>(entities[i])) {
 
 1805                } 
else if ((signatureBitset &
 
 1806                            std::get<BitsetType>(entities[i])) ==
 
 1808                    fn(i, 
this, userData);
 
 1812            std::array<TPFnDataStructZero, ThreadCount * 2> fnDataAr;
 
 1814            std::size_t s = currentSize / (ThreadCount * 2);
 
 1815            for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
 1816                std::size_t begin = s * i;
 
 1818                if (i == ThreadCount * 2 - 1) {
 
 1826                fnDataAr[i].range = {begin, end};
 
 1827                fnDataAr[i].manager = 
this;
 
 1828                fnDataAr[i].entities = &entities;
 
 1829                fnDataAr[i].signature = &signatureBitset;
 
 1830                fnDataAr[i].userData = userData;
 
 1831                for (std::size_t j = begin; j < end; ++j) {
 
 1833                        fnDataAr[i].dead.insert(j);
 
 1836                threadPool->queueFn(
 
 1839                        for (std::size_t i = data->range[0]; i < data->range[1];
 
 1841                            if (data->dead.find(i) != data->dead.end()) {
 
 1843                            } 
else if ((*data->signature &
 
 1844                                        std::get<BitsetType>(data->entities->at(
 
 1845                                            i))) == *data->signature) {
 
 1846                                fn(i, data->manager, data->userData);
 
 1852            threadPool->easyStartAndWait();
 
 1858                std::lock_guard<std::mutex> lock(idStackMutex);
 
 1859                if (idStack.back() == current_id) {
 
 1864            std::this_thread::sleep_for(std::chrono::microseconds(15));
 
 1867        handleDeferredDeletions();
 
 
 1889    template <
typename Iterable>
 
 1891                             void* userData = 
nullptr,
 
 1892                             const bool useThreadPool = 
false) {
 
 1893        std::size_t current_id;
 
 1896            std::lock_guard<std::mutex> lock(idStackMutex);
 
 1897            current_id = idStackCounter++;
 
 1898            idStack.push_back(current_id);
 
 1901        deferringDeletions.fetch_add(1);
 
 1902        if (!useThreadPool || !threadPool) {
 
 1904            for (std::size_t i = 0; i < currentSize; ++i) {
 
 1905                if (!std::get<bool>(entities[i])) {
 
 1910                for (
const auto& integralValue : iterable) {
 
 1911                    if (!std::get<BitsetType>(entities[i])
 
 1912                             .getCombinedBit(integralValue)) {
 
 1921                fn(i, 
this, userData);
 
 1924            std::array<TPFnDataStructSeven<Iterable>, ThreadCount * 2> fnDataAr;
 
 1926            std::size_t s = currentSize / (ThreadCount * 2);
 
 1927            for (std::size_t i = 0; i < ThreadCount * 2; ++i) {
 
 1928                std::size_t begin = s * i;
 
 1930                if (i == ThreadCount * 2 - 1) {
 
 1938                fnDataAr[i].range = {begin, end};
 
 1939                fnDataAr[i].manager = 
this;
 
 1940                fnDataAr[i].entities = &entities;
 
 1941                fnDataAr[i].iterable = &iterable;
 
 1942                fnDataAr[i].userData = userData;
 
 1943                for (std::size_t j = begin; j < end; ++j) {
 
 1945                        fnDataAr[i].dead.insert(j);
 
 1948                threadPool->queueFn(
 
 1953                        for (std::size_t i = data->range[0]; i < data->range[1];
 
 1955                            if (data->dead.find(i) != data->dead.end()) {
 
 1959                            for (
const auto& integralValue : *data->iterable) {
 
 1960                                if (!std::get<BitsetType>(data->entities->at(i))
 
 1961                                         .getCombinedBit(integralValue)) {
 
 1970                            fn(i, data->manager, data->userData);
 
 1975            threadPool->easyStartAndWait();
 
 1981                std::lock_guard<std::mutex> lock(idStackMutex);
 
 1982                if (idStack.back() == current_id) {
 
 1987            std::this_thread::sleep_for(std::chrono::microseconds(15));
 
 1990        handleDeferredDeletions();
 
 
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:160
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:151
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:122
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:179
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:169
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:141
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:132
 
Temporary struct used internally by ThreadPool.
Definition Manager.hpp:112
 
Manages an EntityComponent system.
Definition Manager.hpp:70
 
void forMatchingSignaturesPtr(FTuple fTuple, void *userData=nullptr, const bool useThreadPool=false)
Call multiple functions with mulitple signatures on all living entities.
Definition Manager.hpp:1599
 
std::size_t getCurrentSize() const
Returns the current size or number of entities in the system.
Definition Manager.hpp:322
 
std::size_t removeSomeMatchingFunctions(std::initializer_list< std::size_t > list)
Removes all functions that do have the index specified in argument "list".
Definition Manager.hpp:1311
 
bool hasTag(const std::size_t &index) const
Checks whether or not the given Entity has the given Tag.
Definition Manager.hpp:468
 
bool changeForMatchingFunctionContext(std::size_t id, void *userData)
Sets the context pointer of a stored function.
Definition Manager.hpp:1321
 
std::size_t addForMatchingFunction(Function &&function, void *userData=nullptr)
Stores a function in the manager to be called later.
Definition Manager.hpp:957
 
void addTag(const std::size_t &entityID)
Adds the given Tag to the given Entity.
Definition Manager.hpp:554
 
std::size_t keepSomeMatchingFunctions(List list)
Removes all functions that do not have the index specified in argument "list".
Definition Manager.hpp:1255
 
void clearForMatchingFunctions()
Remove all stored functions.
Definition Manager.hpp:1231
 
std::size_t addEntity()
Adds an entity to the system, returning the ID of the entity.
Definition Manager.hpp:237
 
void reset()
Resets the Manager, removing all entities.
Definition Manager.hpp:590
 
const Component * getEntityData(const std::size_t &index) const
Returns a const pointer to a component belonging to the given Entity.
Definition Manager.hpp:410
 
void callForMatchingFunctions(const bool useThreadPool=false)
Call all stored functions.
Definition Manager.hpp:1142
 
void removeComponent(const std::size_t &entityID)
Removes the given Component from the given Entity.
Definition Manager.hpp:535
 
void forMatchingIterable(Iterable iterable, ForMatchingFn fn, void *userData=nullptr, const bool useThreadPool=false)
Similar to forMatchingSimple(), but with a collection of Component/Tag indices.
Definition Manager.hpp:1890
 
void addComponent(const std::size_t &entityID, Args &&... args)
Adds a component to the given Entity.
Definition Manager.hpp:503
 
void forMatchingSimple(ForMatchingFn fn, void *userData=nullptr, const bool useThreadPool=false)
A simple version of forMatchingSignature()
Definition Manager.hpp:1789
 
bool hasComponent(const std::size_t &index) const
Checks whether or not the given Entity has the given Component.
Definition Manager.hpp:454
 
Component * getEntityData(const std::size_t &index)
Returns a pointer to a component belonging to the given Entity.
Definition Manager.hpp:362
 
void removeTag(const std::size_t &entityID)
Removes the given Tag from the given Entity.
Definition Manager.hpp:574
 
std::size_t keepSomeMatchingFunctions(std::initializer_list< std::size_t > list)
Removes all functions that do not have the index specified in argument "list".
Definition Manager.hpp:1279
 
bool callForMatchingFunction(std::size_t id, const bool useThreadPool=false)
Call a specific stored function.
Definition Manager.hpp:1192
 
void forMatchingSignature(Function &&function, void *userData=nullptr, const bool useThreadPool=false)
Calls the given function on all Entities matching the given Signature.
Definition Manager.hpp:677
 
void deleteEntity(std::size_t index)
Marks an entity for deletion.
Definition Manager.hpp:275
 
Component * getEntityComponent(const std::size_t &index)
Returns a pointer to a component belonging to the given Entity.
Definition Manager.hpp:392
 
const Component * getEntityComponent(const std::size_t &index) const
Returns a const pointer to a component belonging to the given Entity.
Definition Manager.hpp:440
 
Manager()
Initializes the manager with a default capacity.
Definition Manager.hpp:195
 
bool removeForMatchingFunction(std::size_t id)
Removes a function that has the given id.
Definition Manager.hpp:1241
 
void forMatchingSignaturePtr(Function *function, void *userData=nullptr, const bool useThreadPool=false)
Calls the given function on all Entities matching the given Signature.
Definition Manager.hpp:812
 
const EntitiesTupleType & getEntityInfo(const std::size_t &index) const
Returns a const reference to an Entity's info.
Definition Manager.hpp:344
 
std::size_t removeSomeMatchingFunctions(List list)
Removes all functions that do have the index specified in argument "list".
Definition Manager.hpp:1294
 
bool hasEntity(const std::size_t &index) const
Checks if the Entity with the given ID is in the system.
Definition Manager.hpp:302
 
void forMatchingSignatures(FTuple fTuple, void *userData=nullptr, const bool useThreadPool=false)
Call multiple functions with mulitple signatures on all living entities.
Definition Manager.hpp:1379
 
bool isAlive(const std::size_t &index) const
Checks if the Entity is not marked as deleted.
Definition Manager.hpp:312