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

- special treatment for constants (to avoid having threads for them running all the time)

- prevent spamming of some messages in debug testable mode
parent 9d03756a
No related branches found
No related tags found
No related merge requests found
......@@ -9,6 +9,7 @@
#define CHIMERATK_APPLICATION_H
#include <mutex>
#include <atomic>
#include <mtca4u/DeviceBackend.h>
#include <ChimeraTK/ControlSystemAdapter/ApplicationBase.h>
......@@ -106,12 +107,23 @@ namespace ChimeraTK {
* This function should generally not be used in user code. */
static void testableModeLock(const std::string& name) {
if(!getInstance().testableMode) return;
if(getInstance().enableDebugTestableMode) {
if(getInstance().enableDebugTestableMode && !getInstance().testableMode_repeatingMutexOwner) {
std::cout << "Application::testableModeLock(): Thread " << testableModeThreadName()
<< " tries to obtain lock for " << name << std::endl;
}
getTestableModeLockObject().lock();
if(getInstance().enableDebugTestableMode) {
if(getInstance().testableMode_lastMutexOwner == std::this_thread::get_id()) {
if(!getInstance().testableMode_repeatingMutexOwner) {
getInstance().testableMode_repeatingMutexOwner = true;
std::cout << "Application::testableModeLock(): Thread " << testableModeThreadName()
<< " repeatedly obtained lock successfully for " << name << ". Further messages will be suppressed." << std::endl;
}
}
else {
getInstance().testableMode_repeatingMutexOwner = false;
}
getInstance().testableMode_lastMutexOwner = std::this_thread::get_id();
if(getInstance().enableDebugTestableMode && !getInstance().testableMode_repeatingMutexOwner) {
std::cout << "Application::testableModeLock(): Thread " << testableModeThreadName()
<< " obtained lock successfully for " << name << std::endl;
}
......@@ -125,7 +137,8 @@ namespace ChimeraTK {
* This function should generally not be used in user code. */
static void testableModeUnlock(const std::string& name) {
if(!getInstance().testableMode) return;
if(getInstance().enableDebugTestableMode) {
if(getInstance().enableDebugTestableMode && (!getInstance().testableMode_repeatingMutexOwner
|| getInstance().testableMode_lastMutexOwner != std::this_thread::get_id())) {
std::cout << "Application::testableModeUnlock(): Thread " << testableModeThreadName()
<< " releases lock for " << name << std::endl;
}
......@@ -240,6 +253,14 @@ namespace ChimeraTK {
/** Flag whether to warn about unconnected variables or not */
bool enableUnconnectedVariablesWarning{false};
/** Last thread which successfully obtained the lock for the testable mode. This is used to prevent spamming
* repeating messages if the same thread acquires and releases the lock in a loop without another thread
* activating in between. */
std::thread::id testableMode_lastMutexOwner;
/** @todo DOCU */
std::atomic<bool> testableMode_repeatingMutexOwner{false};
template<typename UserType>
friend class TestDecoratorRegisterAccessor; // needs access to the testableMode_mutex and testableMode_counter
......
......@@ -413,9 +413,10 @@ void Application::typedMakeConnection(VariableNetwork &network) {
auto consumers = network.getConsumingNodes();
bool useExternalTrigger = network.getTriggerType() == VariableNetwork::TriggerType::external;
bool useFeederTrigger = network.getTriggerType() == VariableNetwork::TriggerType::feeder;
bool constantFeeder = feeder.getType() == NodeType::Constant;
// 1st case: the feeder requires a fixed implementation
if(feeder.hasImplementation()) {
if(feeder.hasImplementation() && !constantFeeder) {
// Create feeding implementation. Note: though the implementation is derived from the feeder, it will be used as
// the implementation of the (or one of the) consumer. Logically, implementations are always pairs of
......@@ -430,10 +431,6 @@ void Application::typedMakeConnection(VariableNetwork &network) {
else if(feeder.getType() == NodeType::ControlSystem) {
feedingImpl = createProcessVariable<UserType>(feeder);
}
else if(feeder.getType() == NodeType::Constant) {
feedingImpl = feeder.getConstAccessor<UserType>();
assert(feedingImpl != nullptr);
}
else {
throw ApplicationExceptionWithID<ApplicationExceptionID::illegalParameter>("Unexpected node type!");
}
......@@ -541,7 +538,7 @@ void Application::typedMakeConnection(VariableNetwork &network) {
}
}
// 2nd case: the feeder does not require a fixed implementation
else { /* !feeder.hasImplementation() */
else if(!constantFeeder) { /* !feeder.hasImplementation() */
// we should be left with an application feeder node
if(feeder.getType() != NodeType::Application) {
throw ApplicationExceptionWithID<ApplicationExceptionID::illegalParameter>("Unexpected node type!");
......@@ -621,6 +618,36 @@ void Application::typedMakeConnection(VariableNetwork &network) {
connectionMade = true;
}
}
else { /* constantFeeder */
assert(feeder.getType() == NodeType::Constant);
auto feedingImpl = feeder.getConstAccessor<UserType>();
assert(feedingImpl != nullptr);
for(auto &consumer : consumers) {
if(consumer.getType() == NodeType::Application) {
consumer.getAppAccessor<UserType>().replace(feedingImpl);
}
else if(consumer.getType() == NodeType::ControlSystem) {
auto impl = createProcessVariable<UserType>(consumer);
impl->accessChannel(0) = feedingImpl->accessChannel(0);
impl->write();
}
else if(consumer.getType() == NodeType::Device) {
auto impl = createDeviceVariable<UserType>(consumer.getDeviceAlias(), consumer.getRegisterName(),
VariableDirection::feeding, consumer.getMode(), consumer.getNumberOfElements());
impl->accessChannel(0) = feedingImpl->accessChannel(0);
impl->write();
}
else if(consumer.getType() == NodeType::TriggerReceiver) {
throw ApplicationExceptionWithID<ApplicationExceptionID::illegalParameter>("Using constants as triggers is not supported!");
}
else {
throw ApplicationExceptionWithID<ApplicationExceptionID::illegalParameter>("Unexpected node type!");
}
}
connectionMade = true;
}
if(!connectionMade) {
throw ApplicationExceptionWithID<ApplicationExceptionID::notYetImplemented>(
......
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