Inhalte

Alarm Message Service: Collection Implementations

Table of Contents

Introduction

Now, the concrete classes for the default factory methods can be programmed.

Doubly Linked Element

The doubly linked element class is just a simple container class to carry the object, and it can point to other doubly linked elements.

Class DoublyLinkedElement
{attribute 'enable_dynamic_creation'}
{attribute 'reflection'}
FUNCTION_BLOCK DoublyLinkedElement EXTENDS Object IMPLEMENTS IDoublyLinkedElement
VAR
	content 			:IObject;
	nextElement 		:IDoublyLinkedElement;
	previousElement 	:IDoublyLinkedElement;
END_VAR
GET PROPERTY className :ClassName


className := 'DoublyLinkedElement';
METHOD compareTo :ComparationResult
VAR_INPUT
	object	:IObject;
END_VAR
VAR
	element :IDoublyLinkedElement;
END_VAR

IF ((THIS^.isObjectNull(object)) AND (THIS^.isObjectNull(THIS^.object))) THEN
	compareTo := ComparationResult.EQUAL;
ELSIF (THIS^.isObjectNull(object)) THEN
	compareTo := ComparationResult.SMALLER;
ELSIF (THIS^.isObjectNull(THIS^.object)) THEN
	compareTo := ComparationResult.GREATER;
ELSIF (__QUERYINTERFACE(object, element)) THEN
	compareTo := THIS^.object.compareTo(element.object);
ELSE
	compareTo := ComparationResult.SMALLER;
END_IF
METHOD FB_init :BOOL
VAR_INPUT
	(* if TRUE, the retain variables are initialized (warm start / cold start) *)
	bInitRetains					:BOOL;
	(* if TRUE, the instance afterwards gets moved into the copy code (online change) *)
	bInCopyCode						:BOOL;
	content 			:IObject;
	next		 		:IDoublyLinkedElement;
	previous		 	:IDoublyLinkedElement;;
END_VAR
VAR
	{attribute 'hide'}
	newHashstate3 :Hashcode;
END_VAR
VAR CONSTANT
	{attribute 'hide'}
	NUMBER_OF_LEFT_SHIFTS :UINT := 17;
	{attribute 'hide'}
	NUMBER_OF_LEFT_ROTATIONS :UINT := 45;
END_VAR
THIS^.content := content;
THIS^.nextElement := next;
THIS^.previousElement := previous;
GET PROPERTY next :IDoublyLinkedElement


next := THIS^.nextElement;
SET PROPERTY next :IDoublyLinkedElement


THIS^.nextElement := next;
GET PROPERTY object :IObject


object := THIS^.content;
GET PROPERTY previous :IDoublyLinkedElement


previous := THIS^.previousElement;
GET PROPERTY previous :IDoublyLinkedElement


previous := THIS^.previousElement;
SET PROPERTY previous :IDoublyLinkedElement


THIS^.previousElement := previous;

Single Thread Object List

Class SingleThreadObjectList
{attribute 'enable_dynamic_creation'}
{attribute 'reflection'}
FUNCTION_BLOCK SingleThreadObjectList EXTENDS Object IMPLEMENTS IList
VAR
	head 			:IDoublyLinkedElement;
	last 			:IDoublyLinkedElement;
	comparator 		:IComparator;
	sorter 			:IListSorter;
	mySize 			:__XWORD;
END_VAR
METHOD append
VAR_INPUT
	object	: IObject;
END_VAR
VAR
	new: IDoublyLinkedElement;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
RETURN(THIS^.isObjectNull(object));

new := THIS^.elementFactory.getNewDoublyLinkedElement(
	object := object,
	previousElement := THIS^.last,
	nextElement := IS_NOT_REFERENCED,
	linkElements := TRUE
);

RETURN(THIS^.isObjectNull(new));

THIS^.last := new;

IF (THIS^.isObjectNull(THIS^.head)) THEN
	THIS^.head := new;
END_IF

THIS^.incrementSize();
GET PROPERTY className :ClassName


className := 'SingleThreadObjectList';
METHOD clear
{warning disable C0139}
WHILE (THIS^.hasElement) DO
	THIS^.pop;
	IF (THIS^.hasElement) THEN
		THIS^.dequeue;
	END_IF
END_WHILE
{warning restore C0139}
METHOD PROTECTED compare :ComparationResult
VAR_INPUT
	element1 :IDoublyLinkedElement;
	element2 :IDoublyLinkedElement;
END_VAR
IF (THIS^.isObjectValid(THIS^.comparator)) THEN
	compare := THIS^.comparator.compare(element1, element2);
ELSIF (THIS^.isObjectValid(element1)) THEN
	compare := element1.compareTo(element2);
ELSIF (THIS^.isObjectValid(element2)) THEN
	compare := ComparationResult.GREATER;
ELSE
	compare := ComparationResult.EQUAL;
END_IF
METHOD compareTo :ComparationResult
VAR_INPUT
	object	: IObject;
END_VAR
VAR
	list :IList;
END_VAR
compareTo := ComparationResult.EQUAL;
IF (THIS^.isObjectNull(object)) THEN
	compareTo := ComparationResult.GREATER;
ELSIF (__QUERYINTERFACE(object, list)) THEN
	IF (THIS^.size < list.size) THEN
		compareTo := ComparationResult.SMALLER;
	ELSIF (THIS^.size > list.size) THEN
		compareTo := ComparationResult.GREATER;
	END_IF
END_IF
METHOD PROTECTED decrementSize
VAR CONSTANT
	SIZE_INCREMENT :__XWORD := 1;
END_VAR
THIS^.mySize := (THIS^.mySize - SIZE_INCREMENT);
GET PROPERTY dequeue :IObject
VAR
	head :IDoublyLinkedElement;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
dequeue := IS_NOT_REFERENCED;
IF (THIS^.isObjectValid(THIS^.head)) THEN
	dequeue := THIS^.head.object;
	head := THIS^.head;
	THIS^.head := head.next;
	THIS^.elementFactory.destructDoublyLinkedElement(
		element := head,
		unlinkElement := TRUE
	);
	IF (THIS^.isObjectNull(THIS^.head)) THEN
		THIS^.last := IS_NOT_REFERENCED;
	END_IF;
	THIS^.decrementSize();
END_IF
GET PROPERTY PRIVATE elementFactory :IDoublyLinkedElementFactory
VAR_INST
	factoryProvider :FactoryProvider(0,0,0,0,0);
	factory			:IDoublyLinkedElementFactory;
END_VAR
IF (THIS^.isObjectNull(factory)) THEN
	factory := factoryProvider.getDoublyLinkedElementFactory();
END_IF
elementFactory := factory;
METHOD FB_exit :BOOL
VAR_INPUT
	(* if TRUE, the exit method is called for exiting an instance that is copied afterwards (online change). *)
	bInCopyCode :BOOL;
END_VAR
THIS^.clear();
METHOD PROTECTED findObject :IDoublyLinkedElement
VAR_INPUT
	object :IObject;
END_VAR
VAR
	head :IDoublyLinkedElement;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
findObject := IS_NOT_REFERENCED;

IF (THIS^.isObjectNull(object) OR THIS^.isObjectNull(THIS^.head)) THEN
	RETURN;
END_IF;

head := THIS^.head;

WHILE (THIS^.isObjectValid(head)) DO
	IF (THIS^.isObjectValid(head.object)) THEN
		IF (head.object.hashcode = object.hashcode) THEN
			findObject := head;
			EXIT;
		ELSE
			head := head.next;
		END_IF
	END_IF
END_WHILE
GET PROPERTY hasElement :BOOL


hasElement := THIS^.isObjectValid(THIS^.head);
METHOD PROTECTED incrementSize
VAR CONSTANT
	SIZE_INCREMENT :__XWORD := 1;
END_VAR
THIS^.mySize := (THIS^.mySize + SIZE_INCREMENT);
METHOD PROTECTED insertBefore
VAR_INPUT
	element :IDoublyLinkedElement;
	newNext :IDoublyLinkedElement;
END_VAR
VAR_OUTPUT
	next :IDoublyLinkedElement := IS_NOT_REFERENCED;
END_VAR
VAR
	oldNext :IDoublyLinkedElement := IS_NOT_REFERENCED;
	newPrevious :IDoublyLinkedElement := IS_NOT_REFERENCED;
	oldPrevious :IDoublyLinkedElement := IS_NOT_REFERENCED;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
THIS^.unlinkElement(element, oldNext => oldNext, oldPrevious => oldPrevious);

IF (THIS^.isObjectValid(newNext)) THEN
	newPrevious := newNext.previous;
END_IF

THIS^.linkElement(newPrevious, element, newNext);
next := oldPrevious;
METHOD PROTECTED insertBehind
VAR_INPUT
	element :IDoublyLinkedElement;
	newPrevious :IDoublyLinkedElement;
END_VAR
VAR_OUTPUT
	next :IDoublyLinkedElement := IS_NOT_REFERENCED;
END_VAR
VAR
	oldNext :IDoublyLinkedElement := IS_NOT_REFERENCED;
	newNext :IDoublyLinkedElement := IS_NOT_REFERENCED;
	oldPrevious :IDoublyLinkedElement := IS_NOT_REFERENCED;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
THIS^.unlinkElement(element, oldNext => oldNext, oldPrevious => oldPrevious);

IF (THIS^.isObjectValid(newPrevious)) THEN
	newNext := newPrevious.next;
END_IF

THIS^.linkElement(newPrevious, element, newNext);
next := oldPrevious;
GET PROPERTY isEmpty :BOOL


isEmpty := THIS^.isObjectNull(THIS^.head);
METHOD isListContainsObject :BOOL
VAR_INPUT
	object	:IObject;
END_VAR
isListContainsObject := THIS^.isObjectValid(THIS^.findObject(object));
METHOD PROTECTED isSortFinished  :BOOL
VAR_INPUT
	element :IDoublyLinkedElement;
END_VAR
VAR_OUTPUT
	retVal :ExecutionState;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
isSortFinished := FALSE;

IF (THIS^.isObjectNull(element)) THEN
	isSortFinished := TRUE;
ELSIF (THIS^.isObjectNull(element.next)) THEN
	THIS^.last := element;
	isSortFinished := TRUE;
END_IF

retVal := SEL(isSortFinished, ExecutionState.BUSY, ExecutionState.SUCCESS);
METHOD iterate :ExecutionState
VAR_INPUT
	execute	:BOOL;
END_VAR
VAR_OUTPUT
	object	:IObject;
END_VAR
VAR_INST
	currentElement :IDoublyLinkedElement;
	actualHead :IDoublyLinkedElement;
	actualLast :IDoublyLinkedElement;
	startSize :__XWORD;
	END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
IF (NOT execute) THEN
	currentElement := THIS^.head;
	THIS^.wasListChanged(FALSE, actualHead, actualLast, startSize);
	object := IS_NOT_REFERENCED;
	iterate := ExecutionState.IDLE;
ELSIF (THIS^.wasListChanged(TRUE, actualHead, actualLast, startSize)) THEN
	iterate := ExecutionState.ABORTED;
	object := IS_NOT_REFERENCED;
ELSIF (THIS^.isObjectValid(currentElement)) THEN
	object := currentElement.object;
	iterate := ExecutionState.BUSY;
	currentElement := currentElement.next;
ELSE
	iterate := ExecutionState.SUCCESS;
	object := IS_NOT_REFERENCED;
END_IF
METHOD PROTECTED linkElement
VAR_INPUT
	previous :IDoublyLinkedElement := IS_NOT_REFERENCED;
	element :IDoublyLinkedElement := IS_NOT_REFERENCED;
	next :IDoublyLinkedElement := IS_NOT_REFERENCED;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
RETURN(THIS^.isObjectNull(element));

element.previous := previous;
element.next := next;

IF (THIS^.isObjectValid(previous)) THEN
	previous.next := element;
END_IF

IF (THIS^.isObjectValid(next)) THEN
	next.previous := element;
END_IF
METHOD PROTECTED mySort :ExecutionState
VAR_INPUT
	execute :BOOL;
END_VAR
VAR_INST
	element :IDoublyLinkedElement;
	actualHead :IDoublyLinkedElement;
	actualLast :IDoublyLinkedElement;
	startSize :__XWORD;
END_VAR
VAR
	cycle :UINT := 0;
	next :IDoublyLinkedElement;
	previous :IDoublyLinkedElement;
END_VAR
VAR CONSTANT
	MAX_CYCLES :UINT := 10;
	CYCLE_INCREMENT :UINT := 1;
END_VAR
IF (NOT execute) THEN
	mySort := ExecutionState.IDLE;
	element := THIS^.head;
	THIS^.wasListChanged(FALSE, actualHead, actualLast, startSize);
	RETURN;
ELSIF (THIS^.wasListChanged(TRUE, actualHead, actualLast, startSize)) THEN
	mySort := ExecutionState.ABORTED;
END_IF

WHILE ((NOT THIS^.isSortFinished(element, retVal => mySort)) AND (cycle < MAX_CYCLES)) DO
	next := element.next;
	previous := next.previous;
	WHILE (THIS^.isObjectValid(previous)) DO
		IF (THIS^.compare(next, previous) >= ComparationResult.SMALLER) THEN
			IF (NOT next.previous.isEqual(previous)) THEN
				THIS^.insertBehind(element := next, newPrevious := previous, next => next);
				EXIT;
			END_IF
		ELSIF (THIS^.isObjectNull(previous.previous)) THEN
			THIS^.head := next;
			THIS^.insertBefore(element := next, newNext := previous, next => next);
			EXIT;
		END_IF
		previous := previous.previous;
	END_WHILE
	element := next;
	cycle := cycle+CYCLE_INCREMENT;
END_WHILE

THIS^.wasListChanged(FALSE, actualHead, actualLast, startSize);
GET PROPERTY pop :IObject
VAR
	last :IDoublyLinkedElement;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
pop := IS_NOT_REFERENCED;
IF (THIS^.isObjectValid(THIS^.last)) THEN
	pop := THIS^.last.object;
	last := THIS^.last;
	
	THIS^.last := last.previous;
	THIS^.elementFactory.destructDoublyLinkedElement(
		element := last,
		unlinkElement := TRUE
	);
	
	IF (THIS^.isObjectNull(THIS^.last)) THEN
		THIS^.head := IS_NOT_REFERENCED;
	END_IF;
	
	THIS^.decrementSize();
END_IF
METHOD prepend
VAR_INPUT
	object	:IObject;
END_VAR
VAR
	new :IDoublyLinkedElement;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
IF (THIS^.isObjectValid(object)) THEN
	new := THIS^.elementFactory.getNewDoublyLinkedElement(
		object := object,
		previousElement := IS_NOT_REFERENCED,
		nextElement := THIS^.head,
		linkElements := TRUE
	);
	IF (THIS^.isObjectValid(new)) THEN
		THIS^.head := new;
		IF (THIS^.isObjectNull(THIS^.last)) THEN
			THIS^.last := new;
		END_IF
	END_IF
	THIS^.incrementSize();
END_IF
METHOD remove
VAR_INPUT
	object	:IObject;
END_VAR
VAR
	element :IDoublyLinkedElement;
END_VAR
element := THIS^.findObject(object);
IF (THIS^.isObjectValid(element)) THEN
	THIS^.elementFactory.destructDoublyLinkedElement(
		element := element,
		unlinkElement := TRUE
	);
END_IF
METHOD setComperator :IList
VAR_INPUT
	comparator	:IComparator;
END_VAR
setComperator := THIS^;
THIS^.comparator := comparator;
METHOD setSorter :IList
VAR_INPUT
	sorter	:IListSorter;
END_VAR
setSorter := THIS^;
THIS^.sorter := sorter;
GET PROPERTY size :__XWORD


size := THIS^.mySize;
METHOD sort :ExecutionState
VAR_INPUT
	execute	:BOOL;
END_VAR
IF (THIS^.isObjectValid(THIS^.sorter)) THEN
	sort := THIS^.xenoSort(execute);
ELSE
	sort := THIS^.mySort(execute);
END_IF
METHOD PROTECTED unlinkElement
VAR_INPUT
	element :IDoublyLinkedElement;
END_VAR
VAR_OUTPUT
	oldNext :IDoublyLinkedElement := IS_NOT_REFERENCED;
	oldPrevious :IDoublyLinkedElement := IS_NOT_REFERENCED;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
RETURN (THIS^.isObjectNull(element));

oldNext := element.next;
oldPrevious := element.previous;

IF (THIS^.isObjectValid(oldPrevious)) THEN
	oldPrevious.next := oldNext;
END_IF

IF (THIS^.isObjectValid(oldNext)) THEN
	oldNext.previous := oldPrevious;
END_IF
METHOD PROTECTED wasListChanged :BOOL
VAR_INPUT
	execute :BOOL;
END_VAR
VAR_IN_OUT
	actualHead :IDoublyLinkedElement;
	actualLast :IDoublyLinkedElement;
	startSize :__XWORD;
END_VAR
wasListChanged := TRUE;

IF (NOT execute) THEN
	actualHead := THIS^.head;
	actualLast := THIS^.last;
	startSize := THIS^.size;
	wasListChanged := FALSE;
ELSIF (THIS^.isObjectNull(actualHead) <> THIS^.isObjectNull(THIS^.head)) THEN;
ELSIF (THIS^.isObjectNull(actualLast) <> THIS^.isObjectNull(THIS^.last)) THEN;
ELSIF (startSize <> THIS^.size) THEN;
ELSE
	wasListChanged := FALSE;
	IF (THIS^.isObjectValid(THIS^.head)) THEN
		wasListChanged := (NOT THIS^.head.isEqual(actualHead));
	END_IF
	IF (THIS^.isObjectValid(THIS^.head) AND (NOT wasListChanged)) THEN
		wasListChanged := (NOT THIS^.last.isEqual(actualLast));
	END_IF
END_IF
METHOD PROTECTED xenoSort :ExecutionState
VAR_INPUT
	execute :BOOL;
END_VAR
IF (NOT execute) THEN
	THIS^.sorter.head := THIS^.head;
	THIS^.sorter.last := THIS^.last;
	xenoSort := THIS^.sorter.sort(execute);
ELSE
	xenoSort := THIS^.sorter.sort(execute);
	THIS^.head := THIS^.sorter.head;
	THIS^.last := THIS^.sorter.last;
END_IF

Synchronized Object List

As already mentioned, the SingleThreadObjectList class is the only one that is fully programmed. This is just an example of how it works.

Class SynchronizedObjectList
{attribute 'enable_dynamic_creation'}
{attribute 'reflection'}
FUNCTION_BLOCK SynchronizedObjectList EXTENDS Object IMPLEMENTS IList
VAR
	{attribute 'hide'}
	lockObject 			:TC2_System.FB_IecCriticalSection;
END_VAR

GET PROPERTY PRIVATE listFactory :IObjectListFactory
VAR_INST
	factoryProvider		:FactoryProvider(0,0,0,0,0);
	factory				:IObjectListFactory;
	factoryLockObject	:TC2_System.FB_IecCriticalSection;
END_VAR
factoryLockObject.Enter();
IF (THIS^.isObjectNull(factory)) THEN
	factory := factoryProvider.getObjectListFactory();
END_IF
listFactory := factory;
factoryLockObject.Leave();

GET PROPERTY PRIVATE singleThreadList :IList
VAR_INST
	listLockObject  :TC2_System.FB_IecCriticalSection;
	listInstance	:IList;
END_VAR
listLockObject.Enter();
IF (THIS^.isObjectNull(listInstance)) THEN
	listInstance := THIS^.listFactory.getNewObjectList();
END_IF
singleThreadList := listInstance;
listLockObject.Leave();
GET PROPERTY className :ClassName


className := 'SynchronizedObjectList';
METHOD append
VAR_INPUT
	object	:IObject;
END_VAR
THIS^.lockObject.Enter();
THIS^.singleThreadList.append(object);
THIS^.lockObject.Leave();

METHOD sort :ExecutionState
VAR_INPUT
	execute	:BOOL;
END_VAR
THIS^.lockObject.Enter();
sort := THIS^.singleThreadList.sort(execute);
THIS^.lockObject.Leave();
METHOD setSorter :IList
VAR_INPUT
	sorter	:IListSorter;
END_VAR
setSorter := THIS^;
THIS^.lockObject.Enter();
THIS^.singleThreadList.setSorter(sorter);
THIS^.lockObject.Leave();
METHOD FB_exit :BOOL
VAR_INPUT
	(* if TRUE, the exit method is called for exiting an instance that is copied afterwards (online change). *)
	bInCopyCode :BOOL;
END_VAR
IF (THIS^.isObjectNull(THIS^.singleThreadList)) THEN;
ELSIF (THIS^.isObjectValid(THIS^.listFactory)) THEN
	THIS^.listFactory.destructObjectList(THIS^.singleThreadList);
END_IF

Alarm Message Queue

As already mentioned, the SingleThreadObjectList class is the only one that is fully programmed. This is just an example of how it works.

Class AlarmMessageQueue
{attribute 'enable_dynamic_creation'}
{attribute 'reflection'}
FUNCTION_BLOCK AlarmMessageQueue EXTENDS Object IMPLEMENTS IAlarmMessageQueue

GET PROPERTY PRIVATE listFactory :ISynchronizedObjectListFactory
VAR_INST
	factoryProvider		:FactoryProvider(0,0,0,0,0);
	factory				:ISynchronizedObjectListFactory;
	factoryLockObject	:TC2_System.FB_IecCriticalSection;
END_VAR
factoryLockObject.Enter();
IF (THIS^.isObjectNull(factory)) THEN
	factory := factoryProvider.getSynchronizedObjectListFactory();
END_IF
listFactory := factory;
factoryLockObject.Leave();

GET PROPERTY PRIVATE alarmList :IList
VAR_INST
	listLockObject  :TC2_System.FB_IecCriticalSection;
	listInstance	:IList;
END_VAR
listLockObject.Enter();
IF (THIS^.isObjectNull(listInstance)) THEN
	listInstance := THIS^.listFactory.getNewSynchronizedObjectList();
END_IF
alarmList := listInstance;
listLockObject.Leave();
GET PROPERTY PROTECTED isAlarmListValid :BOOL


isAlarmListValid := (THIS^.isObjectValid(THIS^.alarmList));
METHOD PROTECTED toAlarmMessageDto :IAlarmMessageDto
VAR_INPUT
	object :IObject;
END_VAR
VAR CONSTANT
IS_NOT_REFERENCED :__UXINT := 0;
END_VAR

IF (NOT __QUERYINTERFACE(object, toAlarmMessageDto)) THEN
	toAlarmMessageDto := IS_NOT_REFERENCED;
END_IF
GET PROPERTY dequeue :IAlarmMessageDto
VAR CONSTANT
	IS_NOT_REFERENCED :__XWORD := 0;
END_VAR
IF (THIS^.isAlarmListValid) THEN
	dequeue := (THIS^.toAlarmMessageDto(THIS^.alarmList.dequeue));
ELSE
	dequeue := IS_NOT_REFERENCED;
END_IF
METHOD append
VAR_INPUT
	alarmMessage	:IAlarmMessageDto;
END_VAR
IF (THIS^.isAlarmListValid) THEN
	IF (NOT THIS^.alarmList.isListContainsObject(alarmMessage)) THEN
		THIS^.alarmList.append(alarmMessage);
	END_IF
END_IF

Alarm Message Service Subscriber List

As already mentioned, the SingleThreadObjectList class is the only one that is fully programmed. This is just an example of how it works.

Class AlarmMessageServiceSubscriberList
{attribute 'enable_dynamic_creation'}
{attribute 'reflection'}
FUNCTION_BLOCK AlarmMessageServiceSubscriberList EXTENDS Object IMPLEMENTS IAlarmMessageServiceSubscriberList

GET PROPERTY PRIVATE listFactory :ISynchronizedObjectListFactory
VAR_INST
	factoryProvider		:FactoryProvider(0,0,0,0,0);
	factory				:ISynchronizedObjectListFactory;
	factoryLockObject	:TC2_System.FB_IecCriticalSection;
END_VAR
factoryLockObject.Enter();
IF (THIS^.isObjectNull(factory)) THEN
	factory := factoryProvider.getSynchronizedObjectListFactory();
END_IF
listFactory := factory;
factoryLockObject.Leave();
GET PROPERTY PRIVATE subscriberList :IList
VAR_INST
	listLockObject  :TC2_System.FB_IecCriticalSection;
	listInstance	:IList;
END_VAR
listLockObject.Enter();
IF (THIS^.isObjectNull(listInstance)) THEN
	listInstance := THIS^.listFactory.getNewSynchronizedObjectList();
END_IF
subscriberList := listInstance;
listLockObject.Leave();

GET PROPERTY PROTECTED isSubscriberListValid :BOOL


isSubscriberListValid := (THIS^.isObjectValid(THIS^.subscriberList));
METHOD setComperator :IAlarmMessageServiceSubscriberList
VAR_INPUT
	comparator	:IComparator;
END_VAR
setComperator := THIS^;
IF (THIS^.isSubscriberListValid) THEN
	THIS^.subscriberList.setComperator(comparator);
END_IF
METHOD iterateSubscriber :ExecutionState
VAR_INPUT
	execute	:BOOL;
END_VAR
VAR_OUTPUT
	subscriber	:IAlarmMessageService;
END_VAR
VAR CONSTANT
	IS_NOT_REFERENCED :__UXINT := 0;
END_VAR
VAR
	object : IObject;	
END_VAR

IF (THIS^.isSubscriberListValid) THEN
	iterateSubscriber := (THIS^.subscriberList.iterate(execute, object => object));
	IF (NOT __QUERYINTERFACE(object, subscriber)) THEN
		subscriber := IS_NOT_REFERENCED;
		iterateSubscriber := ExecutionState.ERROR;
	END_IF
ELSE
	subscriber := IS_NOT_REFERENCED;
	iterateSubscriber := ExecutionState.ABORTED;
END_IF
METHOD iterate :ExecutionState
VAR_INPUT
	execute	:BOOL;
END_VAR
VAR_OUTPUT
	object	:IObject;
END_VAR
VAR
	subscriber :IAlarmMessageService;
END_VAR
iterate := THIS^.iterateSubscriber(execute, subscriber => subscriber);
object := subscriber;