LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
JobClass.m
1classdef JobClass < NetworkElement
2 % An abstract class for a collection of indistinguishable jobs
3 %
4 % Copyright (c) 2012-2026, Imperial College London
5 % All rights reserved.
6
7 properties
8 priority;
9 deadline; % relative deadline from arrival (Inf = no deadline)
10 refstat; % reference station
11 isrefclass; % is this a reference class within a chain?
12 index; % node index
13 type;
14 completes; % true if passage through reference station is a completion
15 replySignalClass; % Signal class that will unblock servers waiting for reply (for synchronous call semantics)
16 spawnClass; % Class of the job injected at the same station on each service completion of this class (LQN phase-2 continuation)
17 patience; % Global patience distribution for this class (customers abandon queues after patience time)
18 impatienceType; % Global impatience type for this class (ImpatienceType.RENEGING or ImpatienceType.BALKING)
19 immediateFeedback; % Boolean: true if this class uses immediate feedback on self-loops globally
20 end
21
22 methods (Hidden)
23 %Constructor
24 function self = JobClass(type, name)
25 % SELF = JOBCLASS(TYPE, NAME)
26
27 self@NetworkElement(name);
28 self.priority = 0;
29 self.deadline = Inf;
30 self.refstat = Node('Unallocated');
31 self.isrefclass = false;
32 self.index = 1;
33 self.type=type;
34 self.completes = true;
35 self.replySignalClass = [];
36 self.spawnClass = [];
37 self.patience = [];
38 self.impatienceType = [];
39 self.immediateFeedback = false;
40 end
41
42 function self = setReferenceStation(self, source)
43 % SELF = SETREFERENCESTATION(SOURCE)
44
45 self.refstat = source;
46 end
47
48 function self = setReferenceClass(self, bool)
49 % SELF = SETREFERENCECLASS(BOOL)
50 self.isrefclass = bool;
51 end
52
53 function boolIsa = isReferenceStation(self, node)
54 % BOOLISA = ISREFERENCESTATION(NODE)
55
56 boolIsa = strcmp(self.refstat.name,node.name);
57 end
58
59 function boolIsa = isReferenceClass(self)
60 % BOOLISA = ISREFERENCECLASS()
61
62 boolIsa = self.isrefclass;
63 end
64
65 % function self = set.priority(self, priority)
66 % SELF = SET.PRIORITY(PRIORITY)
67
68 % if ~(rem(priority,1) == 0 && priority >= 0)
69 % line_error(mfilename,'Priority must be an integer.\n');
70 % end
71 % self.priority = priority;
72 % end
73 end
74
75 methods (Access=public)
76 function ind = subsindex(self)
77 % IND = SUBSINDEX()
78
79 ind = double(self.index)-1; % 0 based
80 end
81
82 function summary(self)
83 % SUMMARY()
84 line_printf('Class (%s): <strong>%s</strong>',self.type,self.getName);
85 end
86
87 function self = setPriority(self, priority)
88 % SELF = SETPRIORITY(PRIORITY)
89 % Set the priority of this class (0 = highest). Used by the
90 % line-opt ClassPriority decision variable.
91 if ~(rem(priority,1) == 0 && priority >= 0)
92 line_error(mfilename,'Priority must be a non-negative integer.\n');
93 end
94 self.priority = priority;
95 end
96
97 function self = setReplySignalClass(self, replyClass)
98 % SETREPLYSIGNALCLASS Set the Signal class for synchronous call reply
99 %
100 % self = SETREPLYSIGNALCLASS(self, replyClass) configures this job
101 % class to expect a reply signal from the specified Signal class.
102 % When a job of this class completes service, the server will block
103 % until receiving a REPLY signal from the specified class.
104 %
105 % This implements LQN-style synchronous call semantics where a
106 % client sends a request, blocks waiting for a reply, and then
107 % continues processing after the reply arrives.
108 %
109 % @param replyClass Signal object with SignalType.REPLY that will unblock the server
110 % @return self The modified JobClass instance
111
112 if ~isa(replyClass, 'Signal')
113 line_error(mfilename, 'Reply class must be a Signal.');
114 end
115 if replyClass.signalType ~= SignalType.REPLY
116 line_error(mfilename, 'Reply class must have SignalType.REPLY.');
117 end
118 self.replySignalClass = replyClass;
119 end
120
121 function idx = getReplySignalClassIndex(self)
122 % GETREPLYSIGNALCLASSINDEX Get the index of the reply signal class
123 %
124 % idx = GETREPLYSIGNALCLASSINDEX(self) returns the index of the
125 % Signal class that will unblock servers waiting for this class,
126 % or -1 if no reply is expected.
127 %
128 % @return idx Index of reply signal class, or -1 if none
129
130 if isempty(self.replySignalClass)
131 idx = -1;
132 else
133 idx = self.replySignalClass.index;
134 end
135 end
136
137 function self = setSpawnClass(self, spawnCls)
138 % SELF = SETSPAWNCLASS(SPAWNCLS)
139 %
140 % On each service completion of a job of this class, a new job
141 % of class SPAWNCLS is injected at the same station. Used for
142 % LQN phase-2 continuations, where the reply token returns to
143 % the caller while the served task continues its second phase.
144
145 if ~isa(spawnCls, 'JobClass')
146 line_error(mfilename, 'Spawn class must be a JobClass.');
147 end
148 self.spawnClass = spawnCls;
149 end
150
151 function tf = expectsReply(self)
152 % EXPECTSREPLY Check if this class expects a reply signal
153 %
154 % tf = EXPECTSREPLY(self) returns true if this class has been
155 % configured to expect a reply signal (via setReplySignalClass).
156 %
157 % @return tf True if a reply signal is expected
158
159 tf = ~isempty(self.replySignalClass);
160 end
161
162 function self = setPatience(self, varargin)
163 % SELF = SETPATIENCE(DISTRIBUTION) - Backwards compatible
164 % SELF = SETPATIENCE(IMPATIENCETYPE, DISTRIBUTION) - Explicit type
165 %
166 % Sets the global impatience type and distribution for this job class.
167 % This applies to all queues unless overridden by queue-specific settings.
168 %
169 % Parameters:
170 % impatienceType - (Optional) ImpatienceType constant (RENEGING or BALKING)
171 % If omitted, defaults to ImpatienceType.RENEGING
172 % distribution - Any LINE distribution (Exp, Erlang, HyperExp, etc.)
173 % excluding modulated processes (BMAP, MAP, MMPP2)
174 %
175 % Examples:
176 % jobclass.setPatience(Exp(0.1)) % Defaults to RENEGING
177 % jobclass.setPatience(ImpatienceType.RENEGING, Exp(0.1))
178 % jobclass.setPatience(ImpatienceType.BALKING, Det(5.0))
179
180 % Handle backwards compatibility: 1 or 2 arguments
181 if length(varargin) == 1
182 % Old signature: setPatience(distribution)
183 distribution = varargin{1};
184 impatienceType = ImpatienceType.RENEGING; % Default to RENEGING
185 elseif length(varargin) == 2
186 % New signature: setPatience(impatienceType, distribution)
187 impatienceType = varargin{1};
188 distribution = varargin{2};
189 else
190 line_error(mfilename, 'Invalid number of arguments. Use setPatience(distribution) or setPatience(impatienceType, distribution)');
191 end
192
193 if isa(distribution, 'BMAP') || isa(distribution, 'MAP') || isa(distribution, 'MMPP2')
194 line_error(mfilename, 'Modulated processes (BMAP, MAP, MMPP2) are not supported for patience distributions.');
195 end
196
197 % Validate impatience type
198 if impatienceType ~= ImpatienceType.RENEGING && impatienceType ~= ImpatienceType.BALKING
199 line_error(mfilename, 'Invalid impatience type. Use ImpatienceType.RENEGING or ImpatienceType.BALKING.');
200 end
201
202 % Only RENEGING is currently supported
203 if impatienceType == ImpatienceType.BALKING
204 line_error(mfilename, 'BALKING impatience type is not yet supported. Use ImpatienceType.RENEGING.');
205 end
206
207 if isempty(self.obj)
208 self.patience = distribution;
209 self.impatienceType = impatienceType;
210 else
211 self.obj.setPatience(impatienceType, distribution.obj);
212 end
213 end
214
215 function distribution = getPatience(self)
216 % DISTRIBUTION = GETPATIENCE()
217 %
218 % Returns the global patience distribution for this job class.
219 %
220 % Returns:
221 % distribution - The patience distribution, or [] if not set
222
223 if isempty(self.obj)
224 if ~isempty(self.patience)
225 distribution = self.patience;
226 else
227 distribution = [];
228 end
229 else
230 distObj = self.obj.getPatience();
231 if isempty(distObj)
232 distribution = [];
233 else
234 % Convert Java object to MATLAB Distribution
235 distribution = Distribution.fromJavaObject(distObj);
236 end
237 end
238 end
239
240 function impatienceType = getImpatienceType(self)
241 % IMPATIENCETYPE = GETIMPATIENCETYPE()
242 %
243 % Returns the global impatience type for this job class.
244 %
245 % Returns:
246 % impatienceType - The impatience type (ImpatienceType constant), or [] if not set
247
248 if isempty(self.obj)
249 if ~isempty(self.impatienceType)
250 impatienceType = self.impatienceType;
251 else
252 impatienceType = [];
253 end
254 else
255 impatienceTypeObj = self.obj.getImpatienceType();
256 if isempty(impatienceTypeObj)
257 impatienceType = [];
258 else
259 impatienceType = ImpatienceType.fromId(impatienceTypeObj.getID());
260 end
261 end
262 end
263
264 function tf = hasPatience(self)
265 % TF = HASPATIENCE()
266 %
267 % Returns true if this class has a patience distribution set.
268
269 dist = self.getPatience();
270 tf = ~isempty(dist) && ~isa(dist, 'Disabled');
271 end
272
273 function self = setImmediateFeedback(self, value)
274 % SETIMMEDIATEFEEDBACK Set immediate feedback for self-loops
275 %
276 % SETIMMEDIATEFEEDBACK(true) enables immediate feedback for this class globally
277 % SETIMMEDIATEFEEDBACK(false) disables immediate feedback for this class
278 %
279 % When enabled, a job of this class that self-loops at any station stays
280 % in service instead of going back to the queue.
281
282 if isempty(self.obj)
283 self.immediateFeedback = logical(value);
284 else
285 self.obj.setImmediateFeedback(logical(value));
286 end
287 end
288
289 function tf = hasImmediateFeedback(self)
290 % HASIMMEDIATEFEEDBACK Check if immediate feedback is enabled
291 %
292 % TF = HASIMMEDIATEFEEDBACK() returns true if immediate feedback is enabled
293
294 if isempty(self.obj)
295 tf = self.immediateFeedback;
296 else
297 tf = self.obj.hasImmediateFeedback();
298 end
299 end
300 end
301
302end
Definition Station.m:245