1classdef Activity < LayeredNetworkElement
2 % A stage of service in a Task of a LayeredNetwork.
4 % Copyright (c) 2012-2026, Imperial College London
9 hostDemandMean; %
double
10 hostDemandSCV; %
double
14 callOrder; %string \in {
'STOCHASTIC',
'DETERMINISTIC'}
15 syncCallDests = cell(0); %
string array
16 syncCallMeans = []; %integer array
17 asyncCallDests = cell(0); %
string array
18 asyncCallMeans = []; %integer array
20 thinkTime; %Distribution
object
21 thinkTimeMean; %
double
23 phase = 1; %integer: phase number (1 or 2)
27 %
public methods, including constructor
30 function obj = Activity(model, name, hostDemand, boundToEntry, callOrder)
31 % OBJ = ACTIVITY(MODEL, NAME, HOSTDEMAND, BOUNDTOENTRY, CALLORDER)
33 if nargin<2 %~exist(
'name',
'var')
34 line_error(mfilename,'Constructor requires to specify at least a name.');
36 obj@LayeredNetworkElement(name);
38 if nargin<3 %~exist('hostDemand','var')
39 hostDemand = GlobalConstants.FineTol;
40 elseif isnumeric(hostDemand) && hostDemand == 0
41 hostDemand = GlobalConstants.FineTol;
43 if nargin<4 %~exist('boundToEntry','var')
46 if nargin<5 %~exist('callOrder','var')
47 callOrder = 'STOCHASTIC';
50 obj.setHostDemand(hostDemand);
51 obj.boundToEntry = boundToEntry;
52 obj.setCallOrder(callOrder);
54 % Initialize default think time
55 obj.thinkTime = Immediate.getInstance();
56 obj.thinkTimeMean = GlobalConstants.FineTol;
57 obj.thinkTimeSCV = GlobalConstants.FineTol;
59 if isa(model,'LayeredNetwork')
60 model.activities{end+1} = obj;
62 elseif isa(model,
'JLayeredNetwork')
63 % JLayeredNetwork support would go here
if it exists
64 obj.obj = jline.lang.layered.Activity(model.obj, name, hostDemand, boundToEntry, callOrder);
65 model.addActivity(obj);
69 function obj = setParent(obj, parent)
70 % OBJ = SETPARENT(OBJ, PARENT)
72 if isa(parent,
'Entry') || isa(parent,
'Task')
73 obj.parentName = parent.name;
76 obj.parentName = parent;
81 function self = on(self, parent)
82 % OBJ = ON(OBJ, PARENT)
83 if ~isa(parent,'Task')
84 line_error(mfilename,'Invalid .on() argument: expected a task.')
86 if isempty(self.parent)
87 parent.addActivity(self);
90 line_error(mfilename,'Parent task already defined.')
94 function obj = setHostDemand(obj, hostDemand)
95 % OBJ = SETHOSTDEMAND(OBJ, HOSTDEMAND)
97 if isnumeric(hostDemand)
98 if hostDemand <= GlobalConstants.FineTol
99 obj.hostDemand = Immediate.getInstance();
100 obj.hostDemandMean = GlobalConstants.FineTol;
101 obj.hostDemandSCV = GlobalConstants.FineTol;
103 obj.hostDemand = Exp(1/hostDemand);
104 obj.hostDemandMean = hostDemand;
105 obj.hostDemandSCV = 1.0;
107 elseif isa(hostDemand,'Distribution')
108 obj.hostDemand = hostDemand;
109 obj.hostDemandMean = hostDemand.getMean();
110 obj.hostDemandSCV = hostDemand.getSCV();
114 function obj = repliesTo(obj, entry)
115 % OBJ = REPLIESTO(OBJ, ENTRY)
117 if ~isempty(obj.parent)
118 switch SchedStrategy.fromText(obj.parent.scheduling)
119 case SchedStrategy.REF
120 line_error(mfilename,'Activities in reference tasks cannot reply.');
122 entry.replyActivity{end+1} = obj.name;
125 entry.replyActivity{end+1} = obj.name;
129 function obj = boundTo(obj, entry)
130 % OBJ = BOUNDTO(OBJ, ENTRY)
132 if isa(entry,
'Entry')
133 obj.boundToEntry = entry.name;
135 obj.boundToEntry = entry;
137 line_error(mfilename,'Wrong entry parameter for boundTo method.');
141 function obj = setCallOrder(obj, callOrder)
142 % OBJ = SETCALLORDER(OBJ, CALLORDER)
144 if strcmpi(callOrder,'STOCHASTIC') || strcmpi(callOrder,'DETERMINISTIC')
145 obj.callOrder = upper(callOrder);
147 obj.callOrder = 'STOCHASTIC';
151 function obj = setThinkTime(obj, thinkTime)
152 % OBJ = SETTHINKTIME(OBJ, THINKTIME)
154 if isnumeric(thinkTime)
155 if thinkTime <= GlobalConstants.FineTol
156 obj.thinkTime = Immediate.getInstance();
157 obj.thinkTimeMean = GlobalConstants.FineTol;
158 obj.thinkTimeSCV = GlobalConstants.FineTol;
160 obj.thinkTime = Exp(1/thinkTime);
161 obj.thinkTimeMean = thinkTime;
162 obj.thinkTimeSCV = 1.0;
164 elseif isa(thinkTime,'Distribution')
165 obj.thinkTime = thinkTime;
166 obj.thinkTimeMean = thinkTime.getMean();
167 obj.thinkTimeSCV = thinkTime.getSCV();
171 function obj = setPhase(obj, phaseNum)
172 % OBJ = SETPHASE(OBJ, PHASENUM)
173 % Set the phase number for this activity.
174 % Phase 1: activities before the reply
is sent
175 % Phase 2: activities after the reply
is sent (post-reply processing)
177 if ~isnumeric(phaseNum) || phaseNum < 1 || phaseNum > 2
178 line_error(mfilename, 'Phase must be 1 or 2.');
180 obj.phase = phaseNum;
185 function obj = synchCall(obj, synchCallDest, synchCallMean)
186 % OBJ = SYNCHCALL(OBJ, SYNCHCALLDEST, SYNCHCALLMEAN)
188 if nargin<3 %~exist('synchCallMean','var')
192 % Get the destination entry name
193 if ischar(synchCallDest)
194 destName = synchCallDest;
196 destName = synchCallDest.name;
199 % Check if this entry
is already in the synchronous call destinations
200 if ~isempty(obj.syncCallDests)
201 for i = 1:length(obj.syncCallDests)
202 if strcmp(obj.syncCallDests{i}, destName)
203 error_msg = sprintf(
'Activity "%s" already has a synchronous call to entry "%s". ', ...
205 error_msg = [error_msg,
'If you intend multiple calls, change the mean number of calls using synchCall(entry, mean_calls) or define an activity graph with explicit precedences.'];
206 line_error(mfilename, error_msg);
211 % Add the
new call destination
212 obj.syncCallDests{length(obj.syncCallDests)+1} = destName;
213 obj.syncCallMeans = [obj.syncCallMeans; synchCallMean];
217 function obj = asynchCall(obj, asynchCallDest, asynchCallMean)
218 % OBJ = ASYNCHCALL(OBJ, ASYNCHCALLDEST, ASYNCHCALLMEAN)
220 if nargin<3 %~exist(
'asynchCallMean',
'var')
221 asynchCallMean = 1.0;
224 % Get the destination entry name
225 if ischar(asynchCallDest)
226 destName = asynchCallDest;
228 destName = asynchCallDest.name;
231 % Check if this entry
is already in the asynchronous call destinations
232 if ~isempty(obj.asyncCallDests)
233 for i = 1:length(obj.asyncCallDests)
234 if strcmp(obj.asyncCallDests{i}, destName)
235 error_msg = sprintf(
'Activity "%s" already has an asynchronous call to entry "%s". ', ...
237 error_msg = [error_msg,
'If you intend multiple calls, change the mean number of calls using asynchCall(entry, mean_calls) or define an activity graph with explicit precedences.'];
238 line_error(mfilename, error_msg);
243 % Add the
new call destination
244 obj.asyncCallDests{length(obj.asyncCallDests)+1} = destName;
245 obj.asyncCallMeans = [obj.asyncCallMeans; asynchCallMean];
248 % Getter methods
for API consistency with Java/Python
249 function val = getHostDemand(obj)
250 % GETHOSTDEMAND Get the host demand distribution
251 val = obj.hostDemand;
254 function val = getHostDemandMean(obj)
255 % GETHOSTDEMANDMEAN Get the mean host demand
256 val = obj.hostDemandMean;
259 function val = getHostDemandSCV(obj)
260 % GETHOSTDEMANDSCV Get the SCV of host demand
261 val = obj.hostDemandSCV;
264 function val = getCallOrder(obj)
265 % GETCALLORDER Get the call order (STOCHASTIC or DETERMINISTIC)
269 function val = getBoundToEntry(obj)
270 % GETBOUNDTOENTRY Get the entry
this activity
is bound to
271 val = obj.boundToEntry;
274 function val = getParent(obj)
275 % GETPARENT Get the parent task
279 function val = getSyncCallDests(obj)
280 % GETSYNCCALLDESTS Get the synchronous call destinations
281 val = obj.syncCallDests;
284 function val = getSyncCallMeans(obj)
285 % GETSYNCCALLMEANS Get the synchronous call means
286 val = obj.syncCallMeans;
289 function val = getAsyncCallDests(obj)
290 % GETASYNCCALLDESTS Get the asynchronous call destinations
291 val = obj.asyncCallDests;
294 function val = getAsyncCallMeans(obj)
295 % GETASYNCCALLMEANS Get the asynchronous call means
296 val = obj.asyncCallMeans;
299 function val = getThinkTimeMean(obj)
300 % GETTHINKTIMEMEAN Get the mean think time
301 val = obj.thinkTimeMean;
304 function val = getPhase(obj)
305 % GETPHASE Get the phase number (1 or 2)