Fix crash bug, improve Unit Test
Crash bug from improperly implemented std::lock_guard for multi-threaded usage of forMatchingSignatures fixed.
This commit is contained in:
parent
0dba6874ad
commit
648e47aae9
2 changed files with 161 additions and 36 deletions
|
@ -24,6 +24,10 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "Meta/Combine.hpp"
|
#include "Meta/Combine.hpp"
|
||||||
#include "Meta/Matching.hpp"
|
#include "Meta/Matching.hpp"
|
||||||
#include "Bitset.hpp"
|
#include "Bitset.hpp"
|
||||||
|
@ -966,8 +970,6 @@ namespace EC
|
||||||
return forMatchingFunctions.erase(index) == 1;
|
return forMatchingFunctions.erase(index) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Call multiple functions with mulitple signatures on all
|
\brief Call multiple functions with mulitple signatures on all
|
||||||
living entities.
|
living entities.
|
||||||
|
@ -1074,8 +1076,10 @@ namespace EC
|
||||||
& std::get<BitsetType>(entities[eid]))
|
& std::get<BitsetType>(entities[eid]))
|
||||||
== signatureBitsets[i])
|
== signatureBitsets[i])
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex>{sigsMutexes[i]};
|
std::lock_guard<std::mutex> guard(
|
||||||
|
sigsMutexes[i]);
|
||||||
multiMatchingEntities[i].push_back(eid);
|
multiMatchingEntities[i].push_back(eid);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1101,19 +1105,20 @@ namespace EC
|
||||||
ForMatchingSignatureHelper<> >;
|
ForMatchingSignatureHelper<> >;
|
||||||
using Index = EC::Meta::IndexOf<decltype(signature),
|
using Index = EC::Meta::IndexOf<decltype(signature),
|
||||||
SigList>;
|
SigList>;
|
||||||
|
constexpr std::size_t index = Index{};
|
||||||
if(threadCount <= 1)
|
if(threadCount <= 1)
|
||||||
{
|
{
|
||||||
for(auto iter = multiMatchingEntities[Index{}].begin();
|
for(auto iter = multiMatchingEntities[index].begin();
|
||||||
iter != multiMatchingEntities[Index{}].end(); ++iter)
|
iter != multiMatchingEntities[index].end(); ++iter)
|
||||||
{
|
{
|
||||||
Helper::call(*iter, *this,
|
Helper::call(*iter, *this,
|
||||||
std::get<Index{}>(funcTuple));
|
std::get<index>(funcTuple));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<std::thread> threads(threadCount);
|
std::vector<std::thread> threads(threadCount);
|
||||||
std::size_t s = multiMatchingEntities[Index{}].size()
|
std::size_t s = multiMatchingEntities[index].size()
|
||||||
/ threadCount;
|
/ threadCount;
|
||||||
for(std::size_t i = 0; i < threadCount; ++i)
|
for(std::size_t i = 0; i < threadCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -1121,7 +1126,7 @@ namespace EC
|
||||||
std::size_t end;
|
std::size_t end;
|
||||||
if(i == threadCount - 1)
|
if(i == threadCount - 1)
|
||||||
{
|
{
|
||||||
end = multiMatchingEntities[Index{}].size();
|
end = multiMatchingEntities[index].size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1131,10 +1136,10 @@ namespace EC
|
||||||
[this, &multiMatchingEntities, &funcTuple]
|
[this, &multiMatchingEntities, &funcTuple]
|
||||||
(std::size_t begin, std::size_t end)
|
(std::size_t begin, std::size_t end)
|
||||||
{
|
{
|
||||||
for(std::size_t i = begin; i < end; ++i)
|
for(std::size_t j = begin; j < end; ++j)
|
||||||
{
|
{
|
||||||
Helper::call(multiMatchingEntities[Index{}][i],
|
Helper::call(multiMatchingEntities[index][j],
|
||||||
*this, std::get<Index{}>(funcTuple));
|
*this, std::get<index>(funcTuple));
|
||||||
}
|
}
|
||||||
}, begin, end);
|
}, begin, end);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include <EC/Meta/Meta.hpp>
|
#include <EC/Meta/Meta.hpp>
|
||||||
#include <EC/EC.hpp>
|
#include <EC/EC.hpp>
|
||||||
|
@ -586,22 +588,35 @@ TEST(EC, ForMatchingSignatures)
|
||||||
{
|
{
|
||||||
EC::Manager<ListComponentsAll, ListTagsAll> manager;
|
EC::Manager<ListComponentsAll, ListTagsAll> manager;
|
||||||
|
|
||||||
auto e = {
|
std::size_t e[] = {
|
||||||
|
manager.addEntity(),
|
||||||
|
manager.addEntity(),
|
||||||
|
manager.addEntity(),
|
||||||
manager.addEntity(),
|
manager.addEntity(),
|
||||||
manager.addEntity(),
|
manager.addEntity(),
|
||||||
manager.addEntity(),
|
manager.addEntity(),
|
||||||
manager.addEntity()
|
manager.addEntity()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto& first = e[0];
|
||||||
|
auto& last = e[6];
|
||||||
|
|
||||||
for(auto id : e)
|
for(auto id : e)
|
||||||
{
|
{
|
||||||
manager.addComponent<C0>(id);
|
if(id != first && id != last)
|
||||||
manager.addComponent<C1>(id);
|
{
|
||||||
manager.addTag<T0>(id);
|
manager.addComponent<C0>(id);
|
||||||
|
manager.addComponent<C1>(id);
|
||||||
|
manager.addTag<T0>(id);
|
||||||
|
|
||||||
auto& c1 = manager.getEntityData<C1>(id);
|
auto& c1 = manager.getEntityData<C1>(id);
|
||||||
c1.vx = 0;
|
c1.vx = 0;
|
||||||
c1.vy = 0;
|
c1.vy = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
manager.addComponent<C0>(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace EC::Meta;
|
using namespace EC::Meta;
|
||||||
|
@ -630,28 +645,85 @@ TEST(EC, ForMatchingSignatures)
|
||||||
|
|
||||||
for(auto id : e)
|
for(auto id : e)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(2, manager.getEntityData<C0>(id).x);
|
if(id != first && id != last)
|
||||||
EXPECT_EQ(2, manager.getEntityData<C0>(id).y);
|
{
|
||||||
EXPECT_EQ(1, manager.getEntityData<C1>(id).vx);
|
EXPECT_EQ(2, manager.getEntityData<C0>(id).x);
|
||||||
EXPECT_EQ(1, manager.getEntityData<C1>(id).vy);
|
EXPECT_EQ(2, manager.getEntityData<C0>(id).y);
|
||||||
|
EXPECT_EQ(1, manager.getEntityData<C1>(id).vx);
|
||||||
|
EXPECT_EQ(1, manager.getEntityData<C1>(id).vy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EXPECT_EQ(1, manager.getEntityData<C0>(id).x);
|
||||||
|
EXPECT_EQ(1, manager.getEntityData<C0>(id).y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unordered_map<std::size_t,int> cx;
|
||||||
|
std::unordered_map<std::size_t,int> cy;
|
||||||
|
std::unordered_map<std::size_t,int> c0x;
|
||||||
|
std::unordered_map<std::size_t,int> c0y;
|
||||||
|
std::unordered_map<std::size_t,int> c1vx;
|
||||||
|
std::unordered_map<std::size_t,int> c1vy;
|
||||||
|
std::mutex cxM;
|
||||||
|
std::mutex cyM;
|
||||||
|
std::mutex c0xM;
|
||||||
|
std::mutex c0yM;
|
||||||
|
std::mutex c1vxM;
|
||||||
|
std::mutex c1vyM;
|
||||||
|
|
||||||
manager.forMatchingSignatures<
|
manager.forMatchingSignatures<
|
||||||
TypeList<TypeList<C0>, TypeList<C0, C1> >
|
TypeList<TypeList<C0>, TypeList<C0, C1> >
|
||||||
>
|
>
|
||||||
(
|
(
|
||||||
std::make_tuple(
|
std::make_tuple(
|
||||||
[] (std::size_t eid, C0& c) {
|
[&first, &last, &cx, &cy, &cxM, &cyM] (std::size_t eid, C0& c) {
|
||||||
EXPECT_EQ(2, c.x);
|
if(eid != first && eid != last)
|
||||||
EXPECT_EQ(2, c.y);
|
{
|
||||||
c.x = 5;
|
{
|
||||||
c.y = 7;
|
std::lock_guard<std::mutex> guard(cxM);
|
||||||
|
cx.insert(std::make_pair(eid, c.x));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(cyM);
|
||||||
|
cy.insert(std::make_pair(eid, c.y));
|
||||||
|
}
|
||||||
|
c.x = 5;
|
||||||
|
c.y = 7;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(cxM);
|
||||||
|
cx.insert(std::make_pair(eid, c.x));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(cyM);
|
||||||
|
cy.insert(std::make_pair(eid, c.y));
|
||||||
|
}
|
||||||
|
c.x = 11;
|
||||||
|
c.y = 13;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[] (std::size_t eid, C0& c0, C1& c1) {
|
[&c0x, &c0y, &c1vx, &c1vy, &c0xM, &c0yM, &c1vxM, &c1vyM]
|
||||||
EXPECT_EQ(5, c0.x);
|
(std::size_t eid, C0& c0, C1& c1) {
|
||||||
EXPECT_EQ(7, c0.y);
|
{
|
||||||
EXPECT_EQ(1, c1.vx);
|
std::lock_guard<std::mutex> guard(c0xM);
|
||||||
EXPECT_EQ(1, c1.vy);
|
c0x.insert(std::make_pair(eid, c0.x));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(c0yM);
|
||||||
|
c0y.insert(std::make_pair(eid, c0.y));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(c1vxM);
|
||||||
|
c1vx.insert(std::make_pair(eid, c1.vx));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(c1vyM);
|
||||||
|
c1vy.insert(std::make_pair(eid, c1.vy));
|
||||||
|
}
|
||||||
|
|
||||||
c1.vx += c0.x;
|
c1.vx += c0.x;
|
||||||
c1.vy += c0.y;
|
c1.vy += c0.y;
|
||||||
|
@ -661,13 +733,61 @@ TEST(EC, ForMatchingSignatures)
|
||||||
}),
|
}),
|
||||||
3
|
3
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for(auto iter = cx.begin(); iter != cx.end(); ++iter)
|
||||||
|
{
|
||||||
|
if(iter->first != first && iter->first != last)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(2, iter->second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EXPECT_EQ(1, iter->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto iter = cy.begin(); iter != cy.end(); ++iter)
|
||||||
|
{
|
||||||
|
if(iter->first != first && iter->first != last)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(2, iter->second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EXPECT_EQ(1, iter->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto iter = c0x.begin(); iter != c0x.end(); ++iter)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(5, iter->second);
|
||||||
|
}
|
||||||
|
for(auto iter = c0y.begin(); iter != c0y.end(); ++iter)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(7, iter->second);
|
||||||
|
}
|
||||||
|
for(auto iter = c1vx.begin(); iter != c1vx.end(); ++iter)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(1, iter->second);
|
||||||
|
}
|
||||||
|
for(auto iter = c1vy.begin(); iter != c1vy.end(); ++iter)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(1, iter->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto eid : e)
|
for(auto eid : e)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(1, manager.getEntityData<C0>(eid).x);
|
if(eid != first && eid != last)
|
||||||
EXPECT_EQ(2, manager.getEntityData<C0>(eid).y);
|
{
|
||||||
EXPECT_EQ(6, manager.getEntityData<C1>(eid).vx);
|
EXPECT_EQ(1, manager.getEntityData<C0>(eid).x);
|
||||||
EXPECT_EQ(8, manager.getEntityData<C1>(eid).vy);
|
EXPECT_EQ(2, manager.getEntityData<C0>(eid).y);
|
||||||
|
EXPECT_EQ(6, manager.getEntityData<C1>(eid).vx);
|
||||||
|
EXPECT_EQ(8, manager.getEntityData<C1>(eid).vy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EXPECT_EQ(11, manager.getEntityData<C0>(eid).x);
|
||||||
|
EXPECT_EQ(13, manager.getEntityData<C0>(eid).y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue