Skip to content
Snippets Groups Projects
Commit 4df7f61a authored by Martin Christoph Hierholzer's avatar Martin Christoph Hierholzer
Browse files

fix: type collisions with constants

Constants (as generated by ApplicationModule::constant()) were causing a
logic_error if accessors of different types were using the same constant
(created with the same value and the same value type upon creation).
This is possible since the type passed to constant() does not have to be
the same as the type of the accessor.

This is now fixed by giving each constant a fully unique name, so every
accessor using a constant will be in its own little variable network.
parent 5a4d7e29
No related branches found
No related tags found
No related merge requests found
......@@ -188,7 +188,14 @@ namespace ChimeraTK {
template<typename T>
std::string EntityOwner::constant(T value) {
return namePrefixConstant + userTypeToUserType<std::string>(value);
// Make sure every constant has its unique name to avoid differently typed inputs to be connected to the same
// constant. Note that the template type argument T may not match the expected type by the application, since the
// type of the constant is determined by the input accessor, not by the type of the value argument of this function.
// We hence need to use both the type name and a unique counter as part of the name. The unique counter lives inside
// this template function and hence counts for each type T separately!
static std::atomic<uint64_t> uid(0);
return namePrefixConstant + "/" + DataType(typeid(T)).getAsString() + "/" + std::to_string(uid++) + "/" +
userTypeToUserType<std::string>(value);
}
/********************************************************************************************************************/
......
......@@ -133,7 +133,12 @@ namespace ChimeraTK {
net.feeder =
VariableNetworkNode{&net.consumers.front().getValueType(), true, net.consumers.front().getNumberOfElements()};
std::string stringValue = net.consumers.front().getName().substr(ApplicationModule::namePrefixConstant.length());
// Extract value from constant name. The format of a constant path name is:
// /@CONST@/<type>/<uniqueId>/<value>
RegisterPath name(net.consumers.front().getName());
auto components = name.getComponents();
assert(components.size() == 4);
std::string stringValue = components[3];
callForType(net.consumers.front().getValueType(), [&](auto t) {
using UserType = decltype(t);
......
......@@ -13,7 +13,7 @@ namespace ChimeraTK {
/*********************************************************************************************************************/
const std::string EntityOwner::namePrefixConstant{"@CONST@"};
const std::string EntityOwner::namePrefixConstant{"/@CONST@"};
/********************************************************************************************************************/
......
......@@ -299,12 +299,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(testConstants, T, test_types) {
app.testModule.consumingPush = {&app.testModule, app.testModule.constant(T(66)), "", ""};
app.testModule.consumingPoll = {&app.testModule, app.testModule.constant(T(77)), "", ""};
// test a second accessor of a different type but defining the constant with the same type as before
ctk::ScalarPollInput<std::string> myStringConstant{&app.testModule, app.testModule.constant(T(66)), "", ""};
ctk::TestFacility tf{app, false};
tf.runApplication();
app.testModule.mainLoopStarted.wait(); // make sure the module's mainLoop() is entered
BOOST_TEST(app.testModule.consumingPush == 66);
BOOST_TEST(app.testModule.consumingPoll == 77);
BOOST_TEST(boost::starts_with(std::string(myStringConstant), "66")); // might be 66 or 66.000000
BOOST_TEST(app.testModule.consumingPush.readNonBlocking() == false);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment