The Process and Thread Components

AADL process components describe the app’s view of a software component. Process components are themselves composed of threads.

Properties and Contained Elements

process

Process components contain a listing of the ports exposed by the device, and a property specifying whether this process is a display or logic component.

Contained Elements:
 
  • features (port) – The ports this process exposes to other components (either other processes or devices).
  • EMv2Annex (errorpropagation) – [Optional] A list of errors that will propagate in, out, or through this process.
Properties:

ProcessType (MAP_Properties::Process_Type) – Whether this process is a logic or display component.

process implementation
Contained Elements:
 
  • subcomponents (thread and data) – References to tasks that compose this process and, optionally, data elements that represent process variables (which should be tagged with ProcessVariable).
  • connections (port connections) – A list of links between the various threads. Note that thread-thread connections are not allowed.

Process implementations contain a listing of the tasks that compose the software component and connections from those tasks to the process’s external ports. There are no process implementation level properties.

thread

Threads correspond to individual units of work such as handling an incoming message or checking for an alarm condition.

Contained Elements:
 

features (port) – The process-level ports this thread either reads from or writes to.

Properties:
  • Period (Timing_Properties::Period) – The task’s period. Ignored for sporadic tasks.
  • Deadline (Timing_Properties::Deadline) – The amount of time that can lapse between the task’s dispatch and completion.
  • WCET (Timing_Properties::Compute_Execution_Time) – A task’s worst case execution time is the most time it will take to complete after dispatch.
  • Dispatch (Thread_Properties::Dispatch_Protocol) – Either sporadic or periodic. Periodic tasks are dispatched once per period, while sporadic tasks are dispatched when a message arrives on their associated port.

Note

There must be one-to-one correspondence (ie, a bijective mapping) between sporadic threads and the combined set of event and event data ports.

thread implementation

Thread implementations are always empty – all behavior is realized in the generated code.

Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package PulseOx_Forwarding_Logic
public
with PulseOx_Forwarding_Types, MAP_Properties;

	process PulseOx_Logic_Process
	features
		SpO2 : in data port PulseOx_Forwarding_Types::SpO2;
		DerivedAlarm : out event port;
	properties
		MAP_Properties::Component_Type => logic;
	end PulseOx_Logic_Process;

	process implementation PulseOx_Logic_Process.imp
	subcomponents
		CheckSpO2Thread : thread CheckSpO2Thread.imp;
	connections
		outgoing_alarm : port CheckSpO2Thread.Alarm -> DerivedAlarm;
	end PulseOx_Logic_Process.imp;
	
	thread CheckSpO2Thread
	features
		Alarm : out event port;
	properties
		Thread_Properties::Dispatch_Protocol => Periodic;
	end CheckSpO2Thread;
	
	thread implementation CheckSpO2Thread.imp
	end CheckSpO2Thread.imp;
	
end PulseOx_Forwarding_Logic;

Translation

Process components translate to two java classes (a user-modifiable class and a supertype that hides MDCF-specific implementation details) that contain one or more tasks, which communicate with one another via shared state. That is, communication within one process is done via shared state, communication between two processes (or a process and a device) is done via port connections, which are realized as messages sent across the underlying middleware.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package mdcf.app.PulseOx_Forwarding_System;

import mdcf.channelservice.common.MdcfMessage;

public class PulseOx_Logic_Process extends PulseOx_Logic_ProcessSuperType {

	public PulseOx_Logic_Process(String GUID) {
		super(GUID);
	}

	@Override
	protected void initComponent() {
		// TODO Fill in custom initialization code here
	}

	@Override
	protected void CheckSpO2ThreadMethod() {
		// TODO: Fill in custom periodic code here
	}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package mdcf.app.PulseOx_Forwarding_System;

import java.util.HashMap;
import java.util.Map;

import mdcf.channelservice.common.MdcfDecodeMessageException;
import mdcf.channelservice.common.MdcfMessage;
import mdcf.channelservice.common.MdcfReceiverPort;
import mdcf.channelservice.common.MdcfSenderPort;
import mdcf.core.ctypes.Task;
import mdcf.core.ctypes.logic.LogicComponent;
import mdcf.core.messagetypes.devicemgmt.PubChannelAssignmentMsg;
import mdcf.core.messagetypes.devicemgmt.SubChannelAssignmentMsg;

public abstract class PulseOx_Logic_ProcessSuperType extends LogicComponent {
	private HashMap<String, Task> taskInstanceMap;
	private HashMap<String, MdcfReceiverPort<?>> receiverPortMap;
	private Integer SpO2Data;

	private MdcfReceiverPort<Integer> SpO2ReceiverPort = new MdcfReceiverPort<>(
			"SpO2In", Integer.class);
	private MdcfSenderPort<Object> DerivedAlarmSenderPort = new MdcfSenderPort<>(
			"DerivedAlarmOut", Object.class);

	public PulseOx_Logic_ProcessSuperType(String GUID) {
		super(GUID, "PulseOx_Logic_Process");
		taskInstanceMap = new HashMap<>();
		receiverPortMap = new HashMap<>();
		taskInstanceMap.put(CheckSpO2ThreadTask.class.getSimpleName(),
				new CheckSpO2ThreadTask());
		receiverPortMap.put(SpO2ReceiverPort.getName(), SpO2ReceiverPort);
	}

	@Override
	public void init() {
		initComponent();
	}

	@Override
	protected Map<String, Task> getTaskInstanceMap() {
		return this.taskInstanceMap;
	}

	@Override
	protected Map<String, MdcfReceiverPort<?>> getReceiverPortMap() {
		return this.receiverPortMap;
	}

	protected Integer getSpO2Data() {
		return SpO2Data;
	}

	@Override
	public void processSubscriberChannelAssignment(
			SubChannelAssignmentMsg subAssign) {
		subscriberChannelAssignmentHelper(subAssign, this.SpO2ReceiverPort);
	}

	@Override
	public void processPublisherChannelAssignment(
			PubChannelAssignmentMsg pubAssign) {
		publisherChannelAssignmentHelper(pubAssign, this.DerivedAlarmSenderPort);
	}

	protected abstract void initComponent();

	protected abstract void CheckSpO2ThreadMethod();

	private void SpO2ListenerOnMessage(MdcfMessage msg, Integer SpO2Data) {
		this.SpO2Data = SpO2Data;
	}

	public class CheckSpO2ThreadTask implements Task {
		@Override
		public void run() {
			CheckSpO2ThreadMethod();
		}
	}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<mdcf.core.ctypes.AppModuleSignature>
  <type>PulseOx_Logic_Process</type>
  <moduleTasks>
    <mdcf.core.ctypes.TaskSignature>
      <type>PERIODIC</type>
      <trigPortName><!-- Placeholder value: Periodic
      tasks are triggered by time, not message
      arrival --> Placeholder</trigPortName>
      <periodMs>50</periodMs>
      <taskName>CheckSpO2Thread</taskName>
      <deadlineMs>50</deadlineMs>
      <wcetMs>5</wcetMs>
    </mdcf.core.ctypes.TaskSignature>
  </moduleTasks>
  <portSignatures>
    <entry>
      <string>SpO2In</string>
      <mdcf.core.ctypes.PortSignature>
        <portName>SpO2In</portName>
        <portDirection>SUBSCRIBE</portDirection>
        <minPeriod>100</minPeriod>
        <maxPeriod>300</maxPeriod>
        <portType>Integer</portType>
      </mdcf.core.ctypes.PortSignature>
    </entry>
    <entry>
      <string>DerivedAlarmOut</string>
      <mdcf.core.ctypes.PortSignature>
        <portName>DerivedAlarmOut</portName>
        <portDirection>PUBLISH</portDirection>
        <minPeriod>100</minPeriod>
        <maxPeriod>300</maxPeriod>
        <portType>Object</portType>
      </mdcf.core.ctypes.PortSignature>
    </entry>
  </portSignatures>
</mdcf.core.ctypes.AppModuleSignature>