Issue 17299: LoopNodeActivation does not properly handle termination due to an activity final node (fuml-rtf) Source: Model Driven Solutions (Mr. Ed Seidewitz, ed-s(at)modeldriven.com) Nature: Uncategorized Issue Severity: Summary: Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01) Subclause: 8.5.3.2.3 LoopNodeActivation If an activity final node directly owned by a loop node fires, then the loop node should terminate. However, the loop node should still produce values on its output pins based on any computations that have happened so far. Currently, when such an activity final node fires, the enclosing loop node is indeed immediately terminated via a call to its terminate(), but this does not actually terminate the loop in LoopNodeActivation::doStructuredActivity(). That loop only terminates once the test part of the loop executes, producing a null value (since all its nodes will no longer be running), which is interpreted as false. Further, the prior call to terminate() removes all tokens from the output pins in the body part of the loop, meaning that they are no longer available to be moved to the output pins of the loop node. As a result, the loop node produces no output, even if outputs have been computed prior to the firing of the final node. Resolution: Agreed. Note that the modification of ActivityFinalNodeActivation in the revised text below to use a terminateAll operation from StructuredActivityNodeActivation allows this new operation to be overridden in LoopNodeActivation to specify “last wishes before termination” functionality. Revised Text: In Subclause 8.5.2.2.3 ActivityFinalNodeActivation, replace the specification for fire with // Terminate the activity execution or structured node activation // containing this activation. Debug.println("[fire] Activity final node " + this.node.name + "..."); if (this.group.activityExecution != null) { this.group.activityExecution.terminate(); } else { this.group.containingNodeActivation.terminateAll(); } In Subclause 8.5.3.2.4 StructuredActivityNodeActivation, replace the specification of the operation terminate with // Terminate the execution of all contained node activations (which // completes the performance of the structured activity node // activation), and then terminate this node itself. this.terminateAll(); super.terminate(); In Figure 8.28, add the operation “terminateAll()” to the class StructuredActivityNodeActivation, and add the following specification for it in Subclause 8.5.3.2.4: terminateAll() // Terminate the execution of all contained node activations (which // completes the performance of the structured activity node // activation). this.activationGroup.terminateAll(); In Subclause 8.5.3.2.3, in operation doStructuredActivity, in the do loop, in the else part of the if statement following the comment “Run the loop”, replace the statement continuing = this.runTest(); with if (this.isRunning()) { continuing = this.runTest(); } After the if statement, replace the statement this.activationGroup.terminateAll(); with if (this.isRunning()) { this.activationGroup.terminateAll(); } else { continuing = false; } After the do loop, surround the final for loop with an if statement “if (this.isRunning()) { … }”. In Figure 8.28, add the (overriding) operation “terminateAll()” to the class LoopNodeActivation, and add the following specification for it to Subclause 8.5.3.2.3: terminateAll() // Copy the values of the body outputs to the loop outputs, and then // terminate all activations in the loop. OutputPinList resultPins = ((LoopNode)this.node).result; for (int i = 0; i < bodyOutputLists.size(); i++) { Values bodyOutputList = bodyOutputLists.getValue(i); OutputPin resultPin = resultPins.getValue(i); this.putTokens(resultPin, bodyOutputList.values); } super.terminateAll(); Actions taken: April 10, 2012: received issue January 7, 2013: closed issue Discussion: End of Annotations:===== m: Ed Seidewitz To: "issue@omg.org" Date: Tue, 10 Apr 2012 21:27:43 -0400 Subject: LoopNodeActivation does not properly handle termination due to an activity final node Thread-Topic: LoopNodeActivation does not properly handle termination due to an activity final node Thread-Index: Ac0XgO5UYy4r/snhQ42ATbe6gUjoDw== Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US X-Mailprotector-Decision: deliver X-Mailprotector-Connection: TLSv1|[10.1.50.226]|10.1.50.226|outbound.mailprotector.net|0|0|0|new|ugly|0|0|0|0 X-Mailprotector-Results: null_ptr subject_50_chars subject_10_spaces clean X-Mailprotector-Score: 80 X-Mailprotector-IP-Analysis: 0, 10.1.50.226, Ugly c=0 p=0 Source New X-Mailprotector-Scan-Diagnostics: 0-0-0-7568-c X-Mailprotector-ID: 6a88a805-bd74-4e17-a7fe-25a662f89ff8 Specification: Semantics of a Foundational Subset for Executable UML Models (fUML) (formal/2011-02-01) Subclause: 8.5.3.2.3 LoopNodeActivation If an activity final node directly owned by a loop node fires, then the loop node should terminate. However, the loop node should still produce values on its output pins based on any computations that have happened so far. Currently, when such an activity final node fires, the enclosing loop node is indeed immediately terminated via a call to its terminate(), but this does not actually terminate the loop in LoopNodeActivation::doStructuredActivity(). That loop only terminates once the test part of the loop executes, producing a null value (since all its nodes will no longer be running), which is interpreted as false. Further, the prior call to terminate() removes all tokens from the output pins in the body part of the loop, meaning that they are no longer available to be moved to the output pins of the loop node. As a result, the loop node produces no output, even if outputs have been computed prior to the firing of the final node.