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