parallel
Short summary
Method to perform a given action on all objects inside the collection.
All objects are invoked with the applier until all are done.
If at any point the applier returns an error the foreach stops and returns an error.
Action to perform needs to implement IApplier.
Attention: This method is single cycle, what means the call waits for all appliers to finish. Therefore none of the appliers should wait for anything (Events/IO/...)
Example:
You have a list of numbers: 1 2 3 and a ConcreteIncrementApplier that can take a number and increment it.
Calling list.forEach(ConcreteIncrementApplier) will increment all numbers in the list, becoming: 2 3 4.
Return: SUCCESS: All appliers returned with SUCCESS
ERROR: The applier returned error for at least one object, or any other error occured
- Return type: CNM_ReturnTypes.SingleExecutionResult
Parameters
| Name | Type | Comment | Kind |
|---|---|---|---|
| applier | CNM_CollectionInterfaces.IApplier | the applier (action) to be used on all obejcts in the collection | input |
Code
Declaration
METHOD parallel :CNM_ReturnTypes.SingleExecutionResult
VAR_INPUT
(*the applier (action) to be used on all obejcts in the collection*)
applier :CNM_CollectionInterfaces.IApplier;
END_VAR
VAR
continueForeach :BOOL;
chained :CNM_CollectionInterfaces.IChainedApplier;
allObjectsAppliedWithSuccess :BOOL;
firstApllierCall :BOOL;
objectState :CNM_ReturnTypes.SingleExecutionState;
currentApplier :CNM_CollectionInterfaces.IApplier;
object :CNM_AbstractObject.IObject;
applierIndex :UDINT;
END_VAR
VAR CONSTANT
NULL : __XWORD := 0;
END_VAR
Implementation
applierIndex := 0;
currentApplier := 0;
continueForeach := TRUE;
IF ((
THIS^.isObjectNull(THIS^.parallelIterator)
) AND_THEN (
THIS^.usedCollection.createNewIterator(iterator => THIS^.parallelIterator)
<> CNM_ReturnTypes.SingleExecutionResult.SUCCESS
)
) THEN
parallel := CNM_ReturnTypes.SingleExecutionResult.ERROR;
RETURN;
END_IF
WHILE THIS^.selectApplier(applier, applierIndex, currentApplier) DO
firstApllierCall := TRUE;
allObjectsAppliedWithSuccess := FALSE;
THIS^.parallelIterator.iterate(FALSE);
WHILE (NOT allObjectsAppliedWithSuccess) DO
allObjectsAppliedWithSuccess := TRUE;
THIS^.parallelIterator.iterate(FALSE);
// call applier for all objects until all are success
WHILE (
THIS^.parallelIterator.iterate(execute := TRUE, object => object)
= CNM_ReturnTypes.SingleExecutionState.BUSY
) DO
IF(currentApplier.accept(object) = CNM_ReturnTypes.SingleExecutionResult.SUCCESS)THEN
IF firstApllierCall THEN currentApplier.apply(FALSE); END_IF;
objectState := currentApplier.apply(TRUE);
CASE objectState OF
CNM_ReturnTypes.SingleExecutionState.SUCCESS:
CONTINUE;
CNM_ReturnTypes.SingleExecutionState.BUSY:
allObjectsAppliedWithSuccess := FALSE;
CONTINUE;
ELSE
parallel := CNM_ReturnTypes.SingleExecutionResult.ERROR;
RETURN;
END_CASE
END_IF
parallel := CNM_ReturnTypes.SingleExecutionResult.ERROR;
RETURN;
END_WHILE
firstApllierCall := FALSE;
END_WHILE
END_WHILE
parallel := CNM_ReturnTypes.SingleExecutionResult.SUCCESS;