static void call(
const std::size_t& entityID,
CType& ctype,
- Function&& function)
+ Function&& function,
+ void* context = nullptr)
{
function(
entityID,
+ context,
ctype.template getEntityData<Types>(entityID)...
);
}
static void callPtr(
const std::size_t& entityID,
CType& ctype,
- Function* function)
+ Function* function,
+ void* context = nullptr)
{
(*function)(
entityID,
+ context,
ctype.template getEntityData<Types>(entityID)...
);
}
void callInstance(
const std::size_t& entityID,
CType& ctype,
- Function&& function) const
+ Function&& function,
+ void* context = nullptr) const
{
ForMatchingSignatureHelper<Types...>::call(
entityID,
ctype,
- std::forward<Function>(function));
+ std::forward<Function>(function),
+ context);
}
template <typename CType, typename Function>
void callInstancePtr(
const std::size_t& entityID,
CType& ctype,
- Function* function) const
+ Function* function,
+ void* context = nullptr) const
{
ForMatchingSignatureHelper<Types...>::callPtr(
entityID,
ctype,
- function);
+ function,
+ context);
}
};
Signature.
The function object given to this function must accept std::size_t
- as its first parameter and Component pointers for the rest of the
- parameters. Tags specified in the Signature are only used as
- filters and will not be given as a parameter to the function.
-
- The second parameter is default 1 (not multi-threaded). If the
- second parameter threadCount is set to a value greater than 1, then
- threadCount threads will be used.
- Note that multi-threading is based on splitting the task of calling
- the function across sections of entities. Thus if there are only
- a small amount of entities in the manager, then using multiple
- threads may not have as great of a speed-up.
+ as its first parameter, void* as its second parameter, and Component
+ pointers for the rest of the parameters. Tags specified in the
+ Signature are only used as filters and will not be given as a
+ parameter to the function.
+
+ The second parameter is default nullptr and will be passed to the
+ function call as the second parameter as a means of providing
+ context (useful when the function is not a lambda function). The
+ third parameter is default 1 (not multi-threaded). If the third
+ parameter threadCount is set to a value greater than 1, then
+ threadCount threads will be used. Note that multi-threading is
+ based on splitting the task of calling the function across sections
+ of entities. Thus if there are only a small amount of entities in
+ the manager, then using multiple threads may not have as great of a
+ speed-up.
Example:
\code{.cpp}
- manager.forMatchingSignature<TypeList<C0, C1, T0>>([] (
- std::size_t ID, C0* component0, C1* component1) {
+ Context c; // some class/struct with data
+ manager.forMatchingSignature<TypeList<C0, C1, T0>>([]
+ (std::size_t ID,
+ void* context,
+ C0* component0, C1* component1)
+ {
// Lambda function contents here
},
+ &c, // "Context" object passed to the function
4 // four threads
);
\endcode
*/
template <typename Signature, typename Function>
void forMatchingSignature(Function&& function,
+ void* context = nullptr,
std::size_t threadCount = 1)
{
using SignatureComponents =
== signatureBitset)
{
Helper::call(i, *this,
- std::forward<Function>(function));
+ std::forward<Function>(function), context);
}
}
}
{
end = s * (i + 1);
}
- threads[i] = std::thread([this, &function, &signatureBitset]
+ threads[i] = std::thread(
+ [this, &function, &signatureBitset, &context]
(std::size_t begin,
std::size_t end) {
for(std::size_t i = begin; i < end; ++i)
== signatureBitset)
{
Helper::call(i, *this,
- std::forward<Function>(function));
+ std::forward<Function>(function), context);
}
}
},
Signature.
The function pointer given to this function must accept std::size_t
- as its first parameter and Component pointers for the rest of the
- parameters. Tags specified in the Signature are only used as
- filters and will not be given as a parameter to the function.
-
- The second parameter is default 1 (not multi-threaded). If the
- second parameter threadCount is set to a value greater than 1, then
- threadCount threads will be used.
- Note that multi-threading is based on splitting the task of calling
- the function across sections of entities. Thus if there are only
- a small amount of entities in the manager, then using multiple
- threads may not have as great of a speed-up.
+ as its first parameter, void* as its second parameter, and
+ Component pointers for the rest of the parameters. Tags specified in
+ the Signature are only used as filters and will not be given as a
+ parameter to the function.
+
+ The second parameter is default nullptr and will be passed to the
+ function call as the second parameter as a means of providing
+ context (useful when the function is not a lambda function). The
+ third parameter is default 1 (not multi-threaded). If the third
+ parameter threadCount is set to a value greater than 1, then
+ threadCount threads will be used. Note that multi-threading is based
+ on splitting the task of calling the function across sections of
+ entities. Thus if there are only a small amount of entities in the
+ manager, then using multiple threads may not have as great of a
+ speed-up.
Example:
\code{.cpp}
- auto function = [] (std::size_t ID, C0* component0,
- C1* component1) {
+ Context c; // some class/struct with data
+ auto function = []
+ (std::size_t ID,
+ void* context,
+ C0* component0, C1* component1)
+ {
// Lambda function contents here
};
manager.forMatchingSignaturePtr<TypeList<C0, C1, T0>>(
&function, // ptr
+ &c, // "Context" object passed to the function
4 // four threads
);
\endcode
*/
template <typename Signature, typename Function>
void forMatchingSignaturePtr(Function* function,
+ void* context = nullptr,
std::size_t threadCount = 1)
{
using SignatureComponents =
if((signatureBitset & std::get<BitsetType>(entities[i]))
== signatureBitset)
{
- Helper::callPtr(i, *this, function);
+ Helper::callPtr(i, *this, function, context);
}
}
}
{
end = s * (i + 1);
}
- threads[i] = std::thread([this, &function, &signatureBitset]
+ threads[i] = std::thread(
+ [this, &function, &signatureBitset, &context]
(std::size_t begin,
std::size_t end) {
for(std::size_t i = begin; i < end; ++i)
& std::get<BitsetType>(entities[i]))
== signatureBitset)
{
- Helper::callPtr(i, *this, function);
+ Helper::callPtr(i, *this, function, context);
}
}
},
private:
std::unordered_map<std::size_t, std::tuple<
BitsetType,
+ void*,
std::function<void(
std::size_t,
- std::vector<std::size_t>)> > >
+ std::vector<std::size_t>,
+ void*)> > >
forMatchingFunctions;
std::size_t functionIndex = 0;
std::size_t). Calling clearForMatchingFunctions() will reset this
counter to zero.
+ Note that the context pointer provided here (default nullptr) will
+ be provided to the stored function when called.
+
Example:
\code{.cpp}
- manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (
- std::size_t ID, C0* component0, C1* component1) {
+ manager.addForMatchingFunction<TypeList<C0, C1, T0>>([]
+ (std::size_t ID,
+ void* context,
+ C0* component0, C1* component1)
+ {
// Lambda function contents here
});
or calling with callForMatchingFunction().
*/
template <typename Signature, typename Function>
- std::size_t addForMatchingFunction(Function&& function)
+ std::size_t addForMatchingFunction(
+ Function&& function,
+ void* context = nullptr)
{
while(forMatchingFunctions.find(functionIndex)
!= forMatchingFunctions.end())
functionIndex,
std::make_tuple(
signatureBitset,
+ context,
[function, helper, this]
- (std::size_t threadCount,
- std::vector<std::size_t> matching)
+ (std::size_t threadCount,
+ std::vector<std::size_t> matching,
+ void* context)
{
if(threadCount <= 1)
{
{
if(isAlive(eid))
{
- helper.callInstancePtr(eid, *this, &function);
+ helper.callInstancePtr(
+ eid, *this, &function, context);
}
}
}
end = s * (i + 1);
}
threads[i] = std::thread(
- [this, &function, &helper]
+ [this, &function, &helper, &context]
(std::size_t begin,
std::size_t end) {
for(std::size_t i = begin; i < end; ++i)
{
if(isAlive(i))
{
- helper.callInstancePtr(i, *this, &function);
+ helper.callInstancePtr(
+ i, *this, &function, context);
}
}
},
/*!
\brief Call all stored functions.
- A second parameter can be optionally used to specify the number
- of threads to use when calling the functions. Otherwise, this
+ The first (and only) parameter can be optionally used to specify the
+ number of threads to use when calling the functions. Otherwise, this
function is by default not multi-threaded.
Note that multi-threading is based on splitting the task of calling
the functions across sections of entities. Thus if there are only
Example:
\code{.cpp}
- manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (
- std::size_t ID, C0* component0, C1* component1) {
+ manager.addForMatchingFunction<TypeList<C0, C1, T0>>([]
+ (std::size_t ID,
+ void* context,
+ C0* component0, C1* component1) {
// Lambda function contents here
});
iter != forMatchingFunctions.end();
++iter)
{
- std::get<1>(iter->second)(threadCount, matching[i++]);
+ std::get<2>(iter->second)(
+ threadCount, matching[i++], std::get<1>(iter->second));
}
}
\code{.cpp}
std::size_t id =
manager.addForMatchingFunction<TypeList<C0, C1, T0>>(
- [] (std::size_t ID, C0* c0, C1* c1) {
+ [] (std::size_t ID, void* context, C0* c0, C1* c1) {
// Lambda function contents here
});
std::vector<std::vector<std::size_t> > matching =
getMatchingEntities(std::vector<BitsetType*>{
&std::get<BitsetType>(iter->second)}, threadCount);
- std::get<1>(iter->second)(threadCount, matching[0]);
+ std::get<2>(iter->second)(
+ threadCount, matching[0], std::get<1>(iter->second));
return true;
}
Example:
\code{.cpp}
- manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (
- std::size_t ID, C0* component0, C1* component1) {
+ manager.addForMatchingFunction<TypeList<C0, C1, T0>>([]
+ (std::size_t ID,
+ void* context,
+ C0* component0, C1* component1)
+ {
// Lambda function contents here
});
return forMatchingFunctions.erase(index) == 1;
}
+ /*!
+ \brief Sets the context pointer of a stored function
+
+ \return True if id is valid and context was updated
+ */
+ bool changeForMatchingFunctionContext(std::size_t id, void* context)
+ {
+ auto f = forMatchingFunctions.find(id);
+ if(f != forMatchingFunctions.end())
+ {
+ std::get<1>(f->second) = context;
+ return true;
+ }
+ return false;
+ }
+
/*!
\brief Call multiple functions with mulitple signatures on all
living entities.
See the Unit Test of this function in src/test/ECTest.cpp for
usage examples.
+ The second parameter (default nullptr) will be provided to every
+ function call as a void* (context).
+
This function was created for the use case where there are many
entities in the system which can cause multiple calls to
forMatchingSignature to be slow due to the overhead of iterating
*/
template <typename SigList, typename FTuple>
void forMatchingSignatures(
- FTuple fTuple, const std::size_t threadCount = 1)
+ FTuple fTuple,
+ void* context = nullptr,
+ const std::size_t threadCount = 1)
{
std::vector<std::vector<std::size_t> > multiMatchingEntities(
SigList::size);
EC::Meta::forEachDoubleTuple(
EC::Meta::Morph<SigList, std::tuple<> >{},
fTuple,
- [this, &multiMatchingEntities, &threadCount]
+ [this, &multiMatchingEntities, &threadCount, &context]
(auto sig, auto func, auto index)
{
using SignatureComponents =
{
if(isAlive(id))
{
- Helper::call(id, *this, func);
+ Helper::call(id, *this, func, context);
}
}
}
end = s * (i + 1);
}
threads[i] = std::thread(
- [this, &multiMatchingEntities, &index, &func]
+ [this, &multiMatchingEntities, &index, &func,
+ &context]
(std::size_t begin, std::size_t end)
{
for(std::size_t j = begin; j < end;
Helper::call(
multiMatchingEntities[index][j],
*this,
- func);
+ func,
+ context);
}
}
}, begin, end);
See the Unit Test of this function in src/test/ECTest.cpp for
usage examples.
+ The second parameter (default nullptr) will be provided to every
+ function call as a void* (context).
+
This function was created for the use case where there are many
entities in the system which can cause multiple calls to
forMatchingSignature to be slow due to the overhead of iterating
*/
template <typename SigList, typename FTuple>
void forMatchingSignaturesPtr(FTuple fTuple,
+ void* context = nullptr,
std::size_t threadCount = 1)
{
std::vector<std::vector<std::size_t> > multiMatchingEntities(
EC::Meta::forEachDoubleTuple(
EC::Meta::Morph<SigList, std::tuple<> >{},
fTuple,
- [this, &multiMatchingEntities, &threadCount]
+ [this, &multiMatchingEntities, &threadCount, &context]
(auto sig, auto func, auto index)
{
using SignatureComponents =
{
if(isAlive(id))
{
- Helper::callPtr(id, *this, func);
+ Helper::callPtr(id, *this, func, context);
}
}
}
end = s * (i + 1);
}
threads[i] = std::thread(
- [this, &multiMatchingEntities, &index, &func]
+ [this, &multiMatchingEntities, &index, &func,
+ &context]
(std::size_t begin, std::size_t end)
{
for(std::size_t j = begin; j < end;
Helper::callPtr(
multiMatchingEntities[index][j],
*this,
- func);
+ func,
+ context);
}
}
}, begin, end);
typedef std::unique_ptr<Base> TestPtr;
+struct Context
+{
+ int a, b;
+};
+
+void assignContextToC0(std::size_t /* id */, void* context, C0* c)
+{
+ Context* contextPtr = (Context*) context;
+ c->x = contextPtr->a;
+ c->y = contextPtr->b;
+}
+
+void assignC0ToContext(std::size_t /* id */, void* context, C0* c)
+{
+ Context* contextPtr = (Context*) context;
+ contextPtr->a = c->x;
+ contextPtr->b = c->y;
+}
+
+void setC0ToOneAndTwo(std::size_t /* id */, void* /* context */, C0* c)
+{
+ c->x = 1;
+ c->y = 2;
+}
+
+void setContextToThreeAndFour(std::size_t /* id */, void* context, C0* /* c */)
+{
+ Context* contextPtr = (Context*) context;
+ contextPtr->a = 3;
+ contextPtr->b = 4;
+}
+
TEST(EC, Bitset)
{
{
vel->vy = 1;
}
- auto posUpdate = [] (std::size_t id, C0* pos, C1* vel) {
+ auto posUpdate = []
+ (std::size_t /* id */, void* /* context */, C0* pos, C1* vel)
+ {
pos->x += vel->vx;
pos->y += vel->vy;
};
- auto updateTag = [] (std::size_t id, C0* pos, C1* vel) {
+ auto updateTag = []
+ (std::size_t /* id */, void* /* context */, C0* pos, C1* vel)
+ {
pos->x = pos->y = vel->vx = vel->vy = 0;
};
std::size_t count = 0;
- auto updateTagOnly = [&count] (std::size_t id) {
+ auto updateTagOnly = [&count] (std::size_t /* id */, void* /* context */) {
std::cout << "UpdateTagOnly was run." << std::endl;
++count;
};
int x = 0;
int y = 0;
manager.forMatchingSignature<EC::Meta::TypeList<C0Ptr> >([&x, &y]
- (std::size_t eID, C0Ptr* ptr) {
+ (std::size_t /* id */, void* /* context */, C0Ptr* ptr) {
x = (*ptr)->x;
y = (*ptr)->y;
});
int result = 0;
- auto getResultFunction = [&result] (std::size_t eID, TestPtr* ptr) {
+ auto getResultFunction = [&result]
+ (std::size_t /* id */, void* /* context */, TestPtr* ptr)
+ {
result = (*ptr)->getInt();
};
manager.addComponent<C3>(eid);
auto f0index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
- [] (std::size_t eid, C0* c0) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0) {
++c0->x;
++c0->y;
});
auto f1index = manager.addForMatchingFunction<EC::Meta::TypeList<C0, C1>>(
- [] (std::size_t eid, C0* c0, C1* c1) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) {
c1->vx = c0->x + 10;
c1->vy = c1->vy + c1->vx + c0->y + 10;
});
auto f2index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
- [] (std::size_t eid, C0* c0) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0) {
c0->x = c0->y = 9999;
});
auto f3index = manager.addForMatchingFunction<EC::Meta::TypeList<C1>>(
- [] (std::size_t eid, C1* c1) {
+ [] (std::size_t /* id */, void* /* context */, C1* c1) {
c1->vx = c1->vy = 10000;
});
EXPECT_EQ(2, manager.removeSomeMatchingFunctions({f2index, f3index}));
auto f4index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
- [] (std::size_t eid, C0* c0) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0) {
c0->x = 999;
c0->y = 888;
});
}
auto f5index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
- [] (std::size_t eid, C0* c0) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0) {
c0->x = 777;
c0->y = 666;
});
}
manager.forMatchingSignature<EC::Meta::TypeList<C0> >(
- [] (const std::size_t& eid, C0* c) {
+ [] (const std::size_t& /* id */, void* /* context */, C0* c) {
c->x = 1;
c->y = 2;
},
+ nullptr,
2
);
}
manager.forMatchingSignature<EC::Meta::TypeList<C0> >(
- [] (const std::size_t& eid, C0* c) {
+ [] (const std::size_t& /* id */, void* /* context */, C0* c) {
c->x = 3;
c->y = 4;
},
+ nullptr,
8
);
}
auto f0 = manager.addForMatchingFunction<EC::Meta::TypeList<C0> >(
- [] (const std::size_t& eid, C0* c) {
+ [] (const std::size_t& /* id */, void* /* context */, C0* c) {
c->x = 1;
c->y = 2;
}
}
auto f1 = manager.addForMatchingFunction<EC::Meta::TypeList<C0> >(
- [] (const std::size_t& eid, C0* c) {
+ [] (const std::size_t& /* id */, void* /* context */, C0* c) {
c->x = 3;
c->y = 4;
}
TypeList<TypeList<C0>, TypeList<C0, C1> >
>(
std::make_tuple(
- [] (std::size_t eid, C0* c) {
+ [] (std::size_t /* id */, void* /* context */, C0* c) {
EXPECT_EQ(c->x, 0);
EXPECT_EQ(c->y, 0);
c->x = 1;
c->y = 1;
},
- [] (std::size_t eid, C0* c0, C1* c1) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) {
EXPECT_EQ(c0->x, 1);
EXPECT_EQ(c0->y, 1);
EXPECT_EQ(c1->vx, 0);
>
(
std::make_tuple(
- [&first, &last, &cx, &cy, &cxM, &cyM] (std::size_t eid, C0* c) {
+ [&first, &last, &cx, &cy, &cxM, &cyM]
+ (std::size_t eid, void* /* context */, C0* c) {
if(eid != first && eid != last)
{
{
}
},
[&c0x, &c0y, &c1vx, &c1vy, &c0xM, &c0yM, &c1vxM, &c1vyM]
- (std::size_t eid, C0* c0, C1* c1) {
+ (std::size_t eid, void* /* context */, C0* c0, C1* c1) {
{
std::lock_guard<std::mutex> guard(c0xM);
c0x.insert(std::make_pair(eid, c0->x));
c0->x = 1;
c0->y = 2;
}),
+ nullptr,
3
);
TypeList<C0, C1>,
TypeList<C0, C1> > >(
std::make_tuple(
- [] (std::size_t eid, C0* c0, C1* c1) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) {
c0->x = 9999;
c0->y = 9999;
c1->vx = 9999;
c1->vy = 9999;
},
- [] (std::size_t eid, C0* c0, C1* c1) {
+ [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) {
c0->x = 10000;
c0->y = 10000;
c1->vx = 10000;
}
}
- const auto func0 = [] (std::size_t eid, C0* c0, C1* c1)
+ const auto func0 = []
+ (std::size_t /* id */, void* /* context */, C0* c0, C1* c1)
{
c0->x = 1;
c0->y = 2;
c1->vx = 3;
c1->vy = 4;
};
- const auto func1 = [] (std::size_t eid, C0* c0)
+ const auto func1 = [] (std::size_t /* id */, void* /* context */, C0* c0)
{
c0->x = 11;
c0->y = 12;
}
// test duplicate signatures
- const auto setTo9999 = [] (std::size_t eid, C0* c0, C1* c1) {
+ const auto setTo9999 = []
+ (std::size_t /* id */, void* /* context */, C0* c0, C1* c1)
+ {
c0->x = 9999;
c0->y = 9999;
c1->vx = 9999;
c1->vy = 9999;
};
- const auto setTo10000 = [] (std::size_t eid, C0* c0, C1* c1) {
+ const auto setTo10000 = []
+ (std::size_t /* id */, void* /* context */, C0* c0, C1* c1)
+ {
c0->x = 10000;
c0->y = 10000;
c1->vx = 10000;
};
}
+TEST(EC, context)
+{
+ EC::Manager<ListComponentsAll, ListTagsAll> manager;
+ auto e0 = manager.addEntity();
+ auto e1 = manager.addEntity();
+
+ manager.addComponent<C0>(e0, 1, 2);
+ manager.addComponent<C0>(e1, 3, 4);
+
+ Context c;
+ c.a = 2000;
+ c.b = 5432;
+
+ EXPECT_EQ(1, manager.getEntityData<C0>(e0)->x);
+ EXPECT_EQ(2, manager.getEntityData<C0>(e0)->y);
+ EXPECT_EQ(3, manager.getEntityData<C0>(e1)->x);
+ EXPECT_EQ(4, manager.getEntityData<C0>(e1)->y);
+
+ manager.forMatchingSignature<EC::Meta::TypeList<C0>>(assignContextToC0, &c);
+
+ EXPECT_EQ(2000, manager.getEntityData<C0>(e0)->x);
+ EXPECT_EQ(5432, manager.getEntityData<C0>(e0)->y);
+ EXPECT_EQ(2000, manager.getEntityData<C0>(e1)->x);
+ EXPECT_EQ(5432, manager.getEntityData<C0>(e1)->y);
+
+ c.a = 1111;
+ c.b = 2222;
+
+ using C0TL = EC::Meta::TypeList<C0>;
+ manager.forMatchingSignatures<EC::Meta::TypeList<C0TL, C0TL, C0TL>>(
+ std::make_tuple(
+ setC0ToOneAndTwo, assignContextToC0, setContextToThreeAndFour),
+ &c);
+ EXPECT_EQ(1111, manager.getEntityData<C0>(e0)->x);
+ EXPECT_EQ(2222, manager.getEntityData<C0>(e0)->y);
+ EXPECT_EQ(1111, manager.getEntityData<C0>(e1)->x);
+ EXPECT_EQ(2222, manager.getEntityData<C0>(e1)->y);
+
+ EXPECT_EQ(3, c.a);
+ EXPECT_EQ(4, c.b);
+
+ manager.forMatchingSignaturesPtr<EC::Meta::TypeList<C0TL, C0TL>>(
+ std::make_tuple(
+ &setC0ToOneAndTwo, &assignC0ToContext),
+ &c);
+
+ EXPECT_EQ(1, c.a);
+ EXPECT_EQ(2, c.b);
+
+ EXPECT_EQ(1, manager.getEntityData<C0>(e0)->x);
+ EXPECT_EQ(2, manager.getEntityData<C0>(e0)->y);
+ EXPECT_EQ(1, manager.getEntityData<C0>(e1)->x);
+ EXPECT_EQ(2, manager.getEntityData<C0>(e1)->y);
+
+ c.a = 1980;
+ c.b = 1990;
+
+ auto fid = manager.addForMatchingFunction<C0TL>(assignContextToC0, &c);
+
+ manager.callForMatchingFunction(fid);
+ EXPECT_EQ(1980, manager.getEntityData<C0>(e0)->x);
+ EXPECT_EQ(1990, manager.getEntityData<C0>(e0)->y);
+ EXPECT_EQ(1980, manager.getEntityData<C0>(e1)->x);
+ EXPECT_EQ(1990, manager.getEntityData<C0>(e1)->y);
+
+ c.a = 2000;
+ c.b = 2010;
+
+ manager.callForMatchingFunctions();
+ EXPECT_EQ(2000, manager.getEntityData<C0>(e0)->x);
+ EXPECT_EQ(2010, manager.getEntityData<C0>(e0)->y);
+ EXPECT_EQ(2000, manager.getEntityData<C0>(e1)->x);
+ EXPECT_EQ(2010, manager.getEntityData<C0>(e1)->y);
+
+ Context altC;
+ altC.a = 999;
+ altC.b = 1999;
+
+ manager.changeForMatchingFunctionContext(fid, &altC);
+ manager.callForMatchingFunctions();
+ EXPECT_EQ(999, manager.getEntityData<C0>(e0)->x);
+ EXPECT_EQ(1999, manager.getEntityData<C0>(e0)->y);
+ EXPECT_EQ(999, manager.getEntityData<C0>(e1)->x);
+ EXPECT_EQ(1999, manager.getEntityData<C0>(e1)->y);
+}