Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement startup behavior for EInit events #298

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

MandKastner
Copy link

Unconnected event pins with the event type EInit of FBs will be triggered automatically during startup

@mx990 mx990 self-requested a review December 24, 2024 18:31
Copy link
Member

@mx990 mx990 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am somewhat troubled that we are adding a separate memory allocation to hold the input event connection counters for all FB instances. In case of the similar monitoring counters, users can at least disable monitoring on constrained devices or if it is simply not needed.

I would like to propose several alternative approaches for discussion:

  1. we use a common counter for all EInit events 1,
  2. we use a mark-and-sweep search when the resource is started, marking all FBs with input connections on EInit events 1 and then triggering all unmarked FBs (also resetting the mark),
  3. we only allocate the counters when SFBInterfaceSpec::mEITypeNames is not nullptr, which would at least reduce the impact for most FBs 2.

In any case, we may want to add a compile-time flag to disable automatic triggering of unconnected EInit events on startup, including any potential overhead incurred thereof.

Footnotes

  1. This would slightly change the semantics if we had multiple EInit events, but maybe we should disallow that anyway? 2

  2. In that case, we should probably also make sure that FB types in the source tree with only EEvent events have mEITypeNames set to nullptr.

@@ -50,6 +50,7 @@ bool CFunctionBlock::initialize() {
#ifdef FORTE_SUPPORT_MONITORING
setupEventMonitoringData();
#endif //FORTE_SUPPORT_MONITORING
mInputEventConnectionCount = std::make_unique<size_t[]>(getFBInterfaceSpec().mNumEIs);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you need to re-create the array when there interface is reconfigured, see callers of setupEventMonitoringData().

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if i understand what you mean. The only caller of setupMonitoringData() is initialize(). In my understanding the existing unique_ptr will give up its ownership and take the new one with the second call of initialize() . With the release the managed memory should be freed and the new array created.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also called in

T::setupEventMonitoringData();
after setting up the interface of a generic FB.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But with @MandKastner current implementation using a std::unique_ptr this does not really matter. Or do I miss something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I missed the point. Yes we need to put a call there as well.

src/core/funcbloc.h Outdated Show resolved Hide resolved
@@ -432,6 +433,7 @@ EMGMResponse CFunctionBlock::changeExecutionState(EMGMCommandType paCommand){
if((E_FBStates::Idle == mFBState) || (E_FBStates::Stopped == mFBState)){
mFBState = E_FBStates::Running;
nRetVal = EMGMResponse::Ready;
triggerEInitEvents();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems this will also trigger EInit events after a reconfiguration or warm restart? Is this the desired behavior?

@MandKastner
Copy link
Author

@mx990 Thank you for your suggestions. I would prefer to keep the infrastructure to check if a event port is connected and go with your 3rd suggestion to reduce allocated memory. As you also suggested i moved the trigger mechanism to a SIFB and perform the recursive search there, this will allow users to decide about the triggering process.

@franz-hoepfinger-4diac
Copy link

I will test this now.
eagerly waiting for this.

@franz-hoepfinger-4diac
Copy link

so, First Test: Failed:
it seems none of the EInit Pins are triggered:

image

@franz-hoepfinger-4diac
Copy link

ahhhhhhhhhhh i see... there is a new FB: E_TRIG!

@franz-hoepfinger-4diac
Copy link

franz-hoepfinger-4diac commented Jan 17, 2025

Working now ... Cool.

image

image

@franz-hoepfinger-4diac
Copy link

on bigger PRojects i get a lot of
ERROR: T#25000000000: External event queue is full, external event dropped!
Messages.

@@ -671,6 +674,18 @@ size_t CFunctionBlock::getToStringBufferSize() const {

}

void CFunctionBlock::triggerEventsOfType(TEventTypeID paEventTypeId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please move to E_TRIG FB

if (getFBInterfaceSpec().mEITypeNames != nullptr) {
for (TEventID eventId = 0; eventId < getFBInterfaceSpec().mNumEIs; eventId++) {
if (getEIType(eventId) == paEventTypeId && !isInputEventConnected(eventId)) {
getResource()->getResourceEventExecution()->startEventChain(CConnectionPoint(this, eventId));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the eventchain execution thread which was used to triggere the R_TRIG fb and add the events to the internal event list.

return nullptr;
}

void FORTE_E_TRIG::triggerEvents(forte::core::CFBContainer* paContainer, TEventTypeID paEventType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

paContainer is not really needed you could call the getResoruce here.

case scmEventREQID:
const TEventTypeID eventTypeId = CStringDictionary::getInstance().getId(var_EVENTTYPE.c_str());
if (eventTypeId != CStringDictionary::scmInvalidStringId) {
triggerEvents(getResource(), eventTypeId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the paECET for triggereEvents so that you do not need to use the external events everywhere.

@azoitl
Copy link
Contributor

azoitl commented Jan 17, 2025

on bigger PRojects i get a lot of ERROR: T#25000000000: External event queue is full, external event dropped! Messages.

I would expect that, we need more memory to handle that. But with my comments from above you only need to make the internal event queue larger

@franz-hoepfinger-4diac
Copy link

on bigger PRojects i get a lot of ERROR: T#25000000000: External event queue is full, external event dropped! Messages.

I would expect that, we need more memory to handle that. But with my comments from above you only need to make the internal event queue larger

Understand.
yes, waiting for this Improvement.
but still a big step forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants