4 % Copyright (c) 2012-2026, Imperial College London
11 queueing; %
true if this is a queueing place (has an embedded queue)
12 serviceProcess; % per-
class service (queue) processes; empty
for ordinary places
13 departureDiscipline; % per-
class depository departure discipline
17 function self = Place(model,name,schedStrategy)
19 % PLACE(MODEL, NAME, SCHEDSTRATEGY)
20 % SCHEDSTRATEGY (optional) turns
the place into a queueing place with
21 % an embedded queue served under
the given scheduling strategy once a
22 % service process
is assigned via setService.
25 if model.isMatlabNative()
26 classes = model.getClasses();
27 self.input = Storage(classes);
28 self.output = Linkage(classes);
30 self.model.addNode(self);
31 self.server = ServiceTunnel();
34 % Places have infinite capacity (like delay
nodes)
35 self.numberOfServers = Inf;
36 self.schedStrategy = SchedStrategy.INF;
37 self.schedStrategyPar = [];
41 self.schedStrategies = [];
43 self.queueing =
false;
44 self.serviceProcess = {};
45 self.departureDiscipline = [];
46 elseif model.isJavaNative()
48 if nargin>=3 && ~isempty(schedStrategy)
49 self.obj = jline.lang.nodes.Place(model.obj, name, jline.lang.constant.SchedStrategy.fromText(SchedStrategy.toText(schedStrategy)));
51 self.obj = jline.lang.nodes.Place(model.obj, name);
53 self.index = model.obj.getNodeIndex(self.obj);
55 if nargin>=3 && ~isempty(schedStrategy)
56 self.schedStrategy = schedStrategy;
61 numOfClasses = length(self.model.getClasses());
62 % Preserve
the embedded-queue scheduling strategy of a queueing
63 % place (set via
the constructor); only ordinary places, whose
64 % strategy
is nominal,
default to FCFS here. Clobbering it would
65 % turn e.g. an infinite-server think place into a single-server
66 % FCFS station on
the next refresh.
68 self.schedStrategy = SchedStrategy.FCFS;
70 self.schedStrategyPar = zeros(1,numOfClasses);
72 % Preserve a user-configured finite place capacity (setClassCapacity
73 %
is called before model.link, which invokes init): a bounded place
is
74 % what makes an open Source->Place->Transition net a finite ergodic
75 % CTMC. Only (re)initialize entries
the user has not set.
76 if isempty(self.classCap)
77 self.classCap = Inf(1,numOfClasses);
78 elseif length(self.classCap) < numOfClasses
79 tmp = Inf(1,numOfClasses);
80 tmp(1:length(self.classCap)) = self.classCap;
84 self.schedStrategies = ones(1, numOfClasses);
86 classes = self.model.getClasses();
87 self.dropRule(classes{r}.index) = DropStrategy.WAITQ;
91 function self = setClassCapacity(self,
class, capacity)
92 % SELF = SETCLASSCAPACITY(CLASS, CAPACITY)
94 % Resolve a JobClass
object to its
column index (mirrors Source.m);
95 % indexing classCap by
the object itself silently fails to store
the
96 % capacity, so
the Place stays unbounded and setClassCapacity
is a
97 % no-op
for the CTMC marking bound.
98 if isa(
class,
'JobClass')
103 self.classCap(r) = capacity;
106 function self = setSchedStrategies(self, class, strategy)
107 % SELF = SETSCHEDSTRATEGIES(CLASS, STRATEGY)
109 self.schedStrategies(class) = strategy;
112 function setService(self, class, distribution)
113 % SETSERVICE(CLASS, DISTRIBUTION)
114 % Assigns a service process to a token color, turning this ordinary
115 % place into a queueing place. The embedded queue serves tokens under
116 %
the place's scheduling strategy;
the first such call installs
the
117 % concrete server section for that strategy.
119 if isa(distribution,'Workflow')
120 distribution = distribution.toPH();
122 if distribution.isImmediate()
123 distribution = Immediate.getInstance();
127 self.installQueueServer();
128 self.queueing = true;
131 self.server.serviceProcess{1, c}{1} =
class;
132 self.server.serviceProcess{1, c}{2} = ServiceStrategy.LI;
133 self.server.serviceProcess{1, c}{3} = distribution;
134 self.serviceProcess{c} = distribution;
135 if length(self.departureDiscipline) < c || self.departureDiscipline(c)==0
136 self.departureDiscipline(c) = DepartureDiscipline.NORMAL;
138 self.model.setInitialized(
false);
140 self.obj.setService(
class.obj, distribution.obj);
141 self.serviceProcess{
class.index} = distribution;
142 self.queueing =
true;
146 function installQueueServer(self)
147 % INSTALLQUEUESERVER()
148 % Installs
the concrete server section matching
the place
's scheduling
149 % strategy, replacing the default ServiceTunnel used by ordinary places.
151 classes = self.model.getClasses();
152 switch SchedStrategy.toId(self.schedStrategy)
153 case SchedStrategy.INF
154 self.server = InfiniteServer(classes);
155 self.numberOfServers = Inf;
156 case {SchedStrategy.PS, SchedStrategy.DPS, SchedStrategy.GPS, SchedStrategy.LPS}
157 self.server = SharedServer(classes);
158 if isinf(self.numberOfServers); self.numberOfServers = 1; end
160 self.server = Server(classes);
161 if isinf(self.numberOfServers); self.numberOfServers = 1; end
163 % A queueing place is a station with finite/infinite capacity like a Queue;
164 % initialize cap/classCap (left empty by the ordinary-place constructor).
165 nclasses = length(classes);
166 if isempty(self.cap); self.cap = Inf; end
167 if isempty(self.classCap); self.classCap = Inf(1,nclasses); end
168 if isempty(self.dropRule)
170 self.dropRule(classes{r}.index) = DropStrategy.WAITQ;
175 function bool = isQueueing(self)
176 % BOOL = ISQUEUEING()
177 bool = self.queueing;
180 function distribution = getService(self, class)
181 % DISTRIBUTION = GETSERVICE(CLASS)
182 distribution = self.serviceProcess{class.index};
185 function setDepartureDiscipline(self, class, discipline)
186 % SETDEPARTUREDISCIPLINE(CLASS, DISCIPLINE)
187 self.departureDiscipline(class.index) = discipline;
188 if ~isempty(self.obj)
189 self.obj.setDepartureDiscipline(class.obj, jline.lang.constant.DepartureDiscipline.fromID(discipline));
193 function self = setMarking(self, state)
194 % SELF = SETMARKING(STATE)
195 % Alias for setState using Petri-net terminology: sets the initial
196 % token marking (number of tokens per class) of this place.
198 self.setState(state);