Issue 13310: An action can consume more tokens from a pin than the allowed multiplicity upper bound (fuml-ftf) Source: Model Driven Solutions (Mr. Ed Seidewitz, ed-s(at)modeldriven.com) Nature: Uncategorized Issue Severity: Summary: Specification: Semantics of a Foundation Subset for Executable UML Models, FTF – Beta 1 (ptc/08-11-03) Sections: 8.5.2.2.15 (ObjectNodeActivation), 8.6.2.2.1 (ActionActivation), 8.6.2.2.7 (OutputPinActivation), 8.6.2.2.8 (PinActivation) Summary: When an action fires, all offered tokens are accepted on all input pins (because the default object flow weight for fUML is “*”). However, an action cannot consume more tokens from an input pin than the multiplicity upper bound for that pin. Any additional tokens remain on the pin, the intent being that they can be consumed if and when the action fires again. However, currently the ActionActivation::getTokens operation (used to get values from the tokens on an input pin) uses the ActivityNodeActivation::takeTokens operation inherited by InputPin. This operation returns all the tokens on the pin and clears them from the pin, without respecting the multiplicity upper bound. As a result, the ActionActivation::getTokens operation does not respect this upper bound either. Proposed resolution: Add the following operation to ObjectNodeActivation: ObjectNodeActivation::takeUnofferedTokens(): Token[*] // Take the next set of unoffered tokens to be offered from this node activation and return them. TokenList tokens = this.getUnofferedTokens(); for (int i = 0; i < tokens.size(); i++) { Token token = tokens.getValue(i); token.withdraw(); } return tokens; (Note: The getUnofferedTokens operation returns a number of tokens equal to the result of the countUnofferedTokens operation. This is overridden in InputPin to limit the count to at most the multiplicity upper bound.) In ActionActivation::getTokens, replace the call to getTokens with a call to getUnofferedTokens. Add the following operation to OutputPinActivation (overriding the inherited operation): OutputPinActivation::fire(incomingTokens: Token[*]) // Add incoming tokens and send offers on outgoing edges. super.fire(incomingTokens); this.sendUnofferedTokens(); In PinActivation::fire, remove the call to this.sendUnofferedTokens. (Note: The change to not automatically send the tokens from an input pin is necessary to avoid having the tokens marked as sent before they are read by an action that is not a structured activity node. An input pin can only have outgoing flows if it is an input pin of a structured activity node anyway, so the sending of offers from input pins should be handled in the semantics of structured activity nodes. This will be addressed in a separate, related issue on structured activity node activations.) Resolution: Change the code as proposed Revised Text: Add the following operation to ObjectNodeActivation: ObjectNodeActivation::takeUnofferedTokens(): Token[*] // Take the next set of unoffered tokens to be offered // from this node activation and return them. TokenList tokens = this.getUnofferedTokens(); for (int i = 0; i < tokens.size(); i++) { Token token = tokens.getValue(i); token.withdraw(); } return tokens; In ActionActivation::getTokens, replace the call to takeTokens with a call to takeUnofferedTokens. [But see also the resolutions to Issue 13873.] Add the following operation to OutputPinActivation (overriding the inherited operation): OutputPinActivation::fire(incomingTokens: Token[*]) // Add incoming tokens and send offers on outgoing edges. super.fire(incomingTokens); this.sendUnofferedTokens(); In PinActivation::fire, remove the call to this.sendUnofferedTokens Actions taken: January 20, 2009: received issue July 23, 2010: closed issue Discussion: End of Annotations:===== ubject: Issue: An action can consume more tokens from a pin than the allowed multiplicity upper bound Date: Tue, 20 Jan 2009 16:25:27 -0500 X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: Issue: An action can consume more tokens from a pin than the allowed multiplicity upper bound thread-index: Acl7RZyz2bRVF2Z7S+ubrviNB5XU1w== From: "Ed Seidewitz" To: Cc: Specification: Semantics of a Foundation Subset for Executable UML Models, FTF . Beta 1 (ptc/08-11-03) Sections: 8.5.2.2.15 (ObjectNodeActivation), 8.6.2.2.1 (ActionActivation), 8.6.2.2.7 (OutputPinActivation), 8.6.2.2.8 (PinActivation) Summary: When an action fires, all offered tokens are accepted on all input pins (because the default object flow weight for fUML is .*.). However, an action cannot consume more tokens from an input pin than the multiplicity upper bound for that pin. Any additional tokens remain on the pin, the intent being that they can be consumed if and when the action fires again. However, currently the ActionActivation::getTokens operation (used to get values from the tokens on an input pin) uses the ActivityNodeActivation::takeTokens operation inherited by InputPin. This operation returns all the tokens on the pin and clears them from the pin, without respecting the multiplicity upper bound. As a result, the ActionActivation::getTokens operation does not respect this upper bound either. Proposed resolution: Add the following operation to ObjectNodeActivation: ObjectNodeActivation::takeUnofferedTokens(): Token[*] // Take the next set of unoffered tokens to be offered from this node activation and return them. TokenList tokens = this.getUnofferedTokens(); for (int i = 0; i < tokens.size(); i++) { Token token = tokens.getValue(i); token.withdraw(); } return tokens; (Note: The getUnofferedTokens operation returns a number of tokens equal to the result of the countUnofferedTokens operation. This is overridden in InputPin to limit the count to at most the multiplicity upper bound.) In ActionActivation::getTokens, replace the call to getTokens with a call to getUnofferedTokens. Add the following operation to OutputPinActivation (overriding the inherited operation): OutputPinActivation::fire(incomingTokens: Token[*]) // Add incoming tokens and send offers on outgoing edges. super.fire(incomingTokens); this.sendUnofferedTokens(); In PinActivation::fire, remove the call to this.sendUnofferedTokens. (Note: The change to not automatically send the tokens from an input pin is necessary to avoid having the tokens marked as sent before they are read by an action that is not a structured activity node. An input pin can only have outgoing flows if it is an input pin of a structured activity node anyway, so the sending of offers from input pins should be handled in the semantics of structured activity nodes. This will be addressed in a separate, related issue on structured activity node activations.)