DJ - The delegate-job type.DQ - The queue-type for delegate jobs.J - The job type.Q - The queue type for jobs.public class CTandem2<DJ extends SimJob,DQ extends SimQueue,J extends SimJob,Q extends CTandem2> extends AbstractSimQueueComposite<DJ,DQ,J,Q>
This special composite queue only allows two distinct queues, one for waiting and a second one for serving. The composite queue bypasses the service part of the first queue, only using its wait and job-selection policies, and bypasses the waiting part of the second queue.
This special model for a composite queue is named the CTandem2 model,
and deviates significantly from, e.g., the LocalStart model
of AbstractSimQueueComposite_LocalStart
and the Encapsulator model in AbstractEncapsulatorSimQueue.
The main purpose of this rather exotic SimQueue is to replace the waiting queue of an existing SimQueue
implementation with another one in order to, e.g., change from FIFO behavior in the waiting area to LIFO behavior.
It attempts to achieve this by controlling the server-access credits on the first sub-queue, the wait queue,
allowing jobs on it to start (one at a time) only if the second queue, the serve queue,
has SimQueue.isStartArmed() set to true.
Jobs that start on the wait queue are then auto-revoked (SimQueue.AutoRevocationPolicy.UPON_START),
and the composite queue (this) lets the job (well, in fact, its delegate job)
arrive on the serve queue.
A real job starts only if and when it is actually moved from the wait to the serve queue.
When the delegate job departs from the serve queue, its real job departs from the composite queue.
Notice that a CTandem2 guarantees that the serve queue is not on queue-access vacation.
always has infinite server-access credits, and always has an empty waiting area.
This explains the three conditions mentioned in SimQueue.isStartArmed().
The interpretation in terms of replacing the wait-behavior and job-selection behavior of the serve queue with that of the wait queue has several complications, and does not hold in general. For instance, the wait queue may never start a job, jobs may depart from its waiting area, and the serve queue may not support the service area at all.
Despite its complications, the CTandem2 can be very useful to
construct non-standard (at least, not available in this library) SimQueue implementations,
and reduces the pressure on this jqueues library to implement all possible combinations
of waiting-area (buffer) size, job-selection policies and number of servers.
For instance, a queueing discipline we have not implemented at this time of writing in jqueues
is multi-server SJF.
There is, however, a multi-server FCFS_c implementation which features an arbitrary finite number of servers,
so we can replace its FIFO waiting-area behavior with SJF with a CTandem2
as shown below (refer to the constructor documentation for more details):
final SimQueue waitQueue = new SJF (eventList);
final SimQueue serveQueue = new FCFS_c (eventList, numberOfServers);
final SimQueue sjf_c = new CTandem2 (eventList, waitQueue, serveQueue, delegateSimJobFactory);
or even (ignoring generic-type arguments):
public class SJF_c extends CTandem2 { public SJF_c (final SimEventList eventList, final int numberOfServers, final DelegateSimJobFactory delegateSimJobFactory) { super (eventList, new SJF (eventList), new FCFS_c (eventList, numberOfServers), delegateSimJobFactory); }@Overridepublic String toStringDefault () { return "SJF_" + ((FCFS_c) getServeQueue ()).getNumberOfServers () + "]"; } }
Copyright (C) 2005-2017 Jan de Jongh, TNO
This file is covered by the LICENSE file in the root of this project.
SimQueueCompositeAbstractSimQueueComposite.RealDelegateJobMapper<J extends SimJob,DJ extends SimJob>AbstractSimEntity.Notifier, AbstractSimEntity.PreNotificationHookSimQueue.AutoRevocationPolicySimEntity.Action, SimEntity.UnknownNotificationTypePolicy, SimEntity.UnknownOperationPolicyrealDelegateJobMappereventsScheduled, SANITYUSE_ARRAY_OPTIMIZATION| Constructor and Description |
|---|
CTandem2(org.javades.jsimulation.r5.SimEventList eventList,
SimQueue<? extends DJ,? extends DQ> waitQueue,
SimQueue<? extends DJ,? extends DQ> serveQueue,
DelegateSimJobFactory delegateSimJobFactory)
Creates compressed tandem queue given an event list, a wait queue and a serve queue,
and an optional factory for delegate jobs.
|
| Modifier and Type | Method and Description |
|---|---|
CTandem2<DJ,DQ,J,Q> |
getCopySimQueue()
Returns a new
CTandem2 object on the same SimEventList with copies of the wait and
serve queues and the same delegate-job factory. |
Object |
getQoS()
Calls super method (in order to make implementation final).
|
Class |
getQoSClass()
Calls super method (in order to make implementation final).
|
DQ |
getServeQueue()
Gets the serve (second, last) queue.
|
DQ |
getWaitQueue()
Gets the wait (first) queue.
|
protected void |
insertJobInQueueUponArrival(J job,
double time)
Creates the delegate job and administers it.
|
protected void |
insertJobInQueueUponStart(J job,
double time)
Performs sanity checks.
|
boolean |
isStartArmed()
Returns the
startArmed state of the serve (i.e., second) queue. |
protected void |
processSubQueueNotifications(List<MultiSimQueueNotificationProcessor.Notification<DJ,DQ>> notifications)
Processes the pending atomic notifications from the sub-queues, one at a time (core sub-queue notification processor).
|
protected void |
queueAccessVacationDropSubClass(double time,
J job)
Calls super method (in order to make implementation final).
|
protected void |
removeJobFromQueueUponDeparture(J departingJob,
double time)
Departure of the given (real) job.
|
protected void |
removeJobFromQueueUponDrop(J job,
double time)
Drops the given (real) job.
|
protected void |
removeJobFromQueueUponRevokation(J job,
double time,
boolean auto)
Removes a job upon successful revocation (as determined by our super-class).
|
protected void |
rescheduleAfterArrival(J job,
double time)
Lets the delegate job arrive at the wait (i.e., first) queue.
|
protected void |
rescheduleAfterDeparture(J departedJob,
double time)
Enforces the scheduled revocation on the sub-queue, if applicable.
|
protected void |
rescheduleAfterDrop(J job,
double time)
Enforces the scheduled revocation on the sub-queue, if applicable.
|
protected void |
rescheduleAfterRevokation(J job,
double time,
boolean auto)
If present, performs the pending revocation on the applicable sub-queue, and check whether that succeeded.
|
protected void |
rescheduleAfterStart(J job,
double time)
Lets the delegate job arrive at the serve queue.
|
protected void |
rescheduleForNewServerAccessCredits(double time)
Sets the server-access credits on the wait queue.
|
protected void |
resetEntitySubClass()
Resets this
CTandem2. |
protected void |
setServerAccessCreditsOnWaitQueue()
Sets the server-access credits on the wait queue, based upon our server-access credits
and the
SimQueue.isStartArmed() state on the server queue. |
protected void |
setServerAccessCreditsSubClass()
Adjusts the server-access credits on the wait queue if needed.
|
String |
toStringDefault()
Returns "CTandem2[waitQueue,serveQueue]".
|
addRealJobLocal, getCopySimQueues, getCopySubSimQueues, getDelegateJob, getDelegateJobMild, getDelegateSimJobFactory, getIndex, getIndex, getQueue, getQueue, getQueues, getRealJob, getRealJob, getSimQueueSelector, isDelegateJob, isRealJob, notifyResetEntity, notifyStateChanged, notifyUpdate, removeJobsFromQueueLocal, resetSimQueueSelector, selectFirstQueue, selectNextQueue, setDelegateSimJobFactoryarrive, autoRevoke, cancelDepartureEvent, cancelDepartureEvent, depart, departureFromEventList, drop, getAutoRevocationPolicy, getDepartureEvents, getDepartureEvents, getFirstJob, getFirstJobInServiceArea, getFirstJobInWaitingArea, getJobs, getJobsInServiceArea, getJobsInWaitingArea, getNumberOfJobs, getNumberOfJobsInServiceArea, getNumberOfJobsInWaitingArea, getServerAccessCredits, getServiceTimeForJob, hasJobs, hasJobsInServiceArea, hasJobsInWaitingArea, hasServerAcccessCredits, isJob, isJobInServiceArea, isJobInWaitingArea, isQueueAccessVacation, registerStdOutSimQueueListener, revoke, revoke, scheduleDepartureEvent, scheduleJobArrival, setAutoRevocationPolicy, setQueueAccessVacation, setServerAccessCredits, start, takeServerAccessCredit, triggerPotentialNewStartArmed, unregisterStdOutSimQueueListeneraddPendingNotification, addPendingNotification, clearAndUnlockPendingNotificationsIfLocked, delegateOperation, doAfterNotifications, doOperation, fireAndLockPendingNotifications, getEventList, getLastUpdateTime, getRegisteredDelegatedOperations, getRegisteredNotificationTypes, getRegisteredOperations, getSimEntityListeners, getUnknownNotificationTypePolicy, getUnknownOperationPolicy, isIgnoreEventListReset, notifyEventListReset, registerDelegatedOperation, registerNotificationType, registerOperation, registerPreEventHook, registerPreNotificationHook, registerPreUpdateHook, registerSimEntityListener, registerStdOutSimEntityListener, removeDelegationForOperation, resetEntity, setIgnoreEventListReset, setName, setUnknownNotificationTypePolicy, setUnknownOperationPolicy, toString, unregisterSimEntityListener, unregisterStdOutSimEntityListener, updateclone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitarrive, getAutoRevocationPolicy, getJobs, getJobsInServiceArea, getJobsInWaitingArea, getNumberOfJobs, getNumberOfJobsInServiceArea, getNumberOfJobsInWaitingArea, getServerAccessCredits, isJob, isJobInServiceArea, isJobInWaitingArea, isQueueAccessVacation, revoke, revoke, setAutoRevocationPolicy, setQueueAccessVacation, setServerAccessCreditsdoAfterNotifications, doOperation, getEventList, getLastUpdateTime, getRegisteredNotificationTypes, getRegisteredOperations, getSimEntityListeners, getUnknownNotificationTypePolicy, getUnknownOperationPolicy, isIgnoreEventListReset, registerSimEntityListener, resetEntity, setIgnoreEventListReset, setName, setUnknownNotificationTypePolicy, setUnknownOperationPolicy, unregisterSimEntityListener, updatepublic CTandem2(org.javades.jsimulation.r5.SimEventList eventList,
SimQueue<? extends DJ,? extends DQ> waitQueue,
SimQueue<? extends DJ,? extends DQ> serveQueue,
DelegateSimJobFactory delegateSimJobFactory)
The constructor invoking the super constructor with an appropriate anonymous SimQueueSelector object,
and then sets the auto-revocation policy on the wait queue to SimQueue.AutoRevocationPolicy.UPON_START.
eventList - The event list to use.waitQueue - The wait queue.serveQueue - The serve queue.delegateSimJobFactory - An optional factory for the delegate SimJobs.IllegalArgumentException - If the event list is null,
one of or both queues are null or equal.DelegateSimJobFactory,
DefaultDelegateSimJobFactory,
getWaitQueue(),
getServeQueue(),
SimQueue.setAutoRevocationPolicy(org.javades.jqueues.r5.entity.jq.queue.SimQueue.AutoRevocationPolicy),
SimQueue.AutoRevocationPolicy.UPON_START,
resetEntitySubClassLocal()public CTandem2<DJ,DQ,J,Q> getCopySimQueue()
CTandem2 object on the same SimEventList with copies of the wait and
serve queues and the same delegate-job factory.CTandem2 object on the same SimEventList with copies of the wait and
serve queues and the same delegate-job factory.UnsupportedOperationException - If the wait or serve queues could not be copied through SimQueue.getCopySimQueue().AbstractSimEntity.getEventList(),
getWaitQueue(),
getServeQueue(),
AbstractSimQueueComposite.getDelegateSimJobFactory()public final DQ getWaitQueue()
public final DQ getServeQueue()
public String toStringDefault()
toStringDefault in interface SimEntitytoStringDefault in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>SimEntity.setName(java.lang.String),
Object.toString()public final Object getQoS()
null.public final Class getQoSClass()
null.protected void resetEntitySubClass()
CTandem2.
Calls super method (not if called from constructor, for which a private variant for local resets is used),
and sets the server-access credits on the wait (first) sub-queue to unity
if the serve (second) queue has SimQueue.isStartArmed() value true,
and zero if not.
resetEntitySubClass in class AbstractSimQueueComposite<DJ extends SimJob,DQ extends SimQueue,J extends SimJob,Q extends CTandem2>SimEntity.resetEntity(),
SimQueue.setServerAccessCredits(double, int),
SimQueue.isStartArmed()protected final void queueAccessVacationDropSubClass(double time,
J job)
queueAccessVacationDropSubClass in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>time - The time the job was dropped, i.e., the current time.job - The dropped job.AbstractSimQueue.arrive(double, J),
AbstractSimQueue.setQueueAccessVacation(double, boolean)public final boolean isStartArmed()
startArmed state of the serve (i.e., second) queue.startArmed state of the serve (i.e., second) queue.SimQueue.isStartArmed()protected final void setServerAccessCreditsOnWaitQueue()
SimQueue.isStartArmed() state on the server queue.
At all times (well, if we have a consistent queue state),
the server-access credits on the wait queue should be unity if and only if
the local (this) queue AbstractSimQueue.hasServerAcccessCredits()
AND the serve queue has SimQueue.isStartArmed().
In all other cases, the server-access credits on the wait queue should be zero.
This method sets the server-access credits on the wait queue appropriately, but only if needed.
Caution is advised for the use of this method.
For one, because of its immediate side effects on the wait (and possibly serve) queue,
you should not use it from within a sub-queue notification listener
(at least, not without taking special measures,
as is done in this class through a MultiSimQueueNotificationProcessor).
This method is (left) protected for documentation (javadoc) purposes.
IllegalStateException - If The current server-access credits value on the wait queue is not zero or unity.AbstractSimQueueComposite.getQueue(int),
AbstractSimEntity.getLastUpdateTime(),
AbstractSimQueue.hasServerAcccessCredits(),
SimQueue.getServerAccessCredits(),
SimQueue.setServerAccessCredits(double, int),
SimQueue.isStartArmed()protected final void insertJobInQueueUponArrival(J job, double time)
insertJobInQueueUponArrival in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The job that arrived.time - The current time (i.e., arrival time of the job).AbstractSimQueueComposite.addRealJobLocal(J),
rescheduleAfterArrival(J, double)protected final void rescheduleAfterArrival(J job, double time)
rescheduleAfterArrival in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The job that arrived (and is already present in AbstractSimQueue.getJobs()).time - The current time (i.e., the arrival time of the job).SimQueue.arrive(double, J),
insertJobInQueueUponArrival(J, double)protected final void removeJobFromQueueUponDrop(J job, double time)
In the CTandem2,
a (real) job can only be dropped because of one of the following two reasons:
processSubQueueNotifications(java.util.List<org.javades.jqueues.r5.listener.MultiSimQueueNotificationProcessor.Notification<DJ, DQ>>).
In this case,
the delegate job has already left the sub-queue system when we are called,
hence no action is required to remove it from there.
All we have to do is invoke AbstractSimQueueComposite.removeJobsFromQueueLocal(J, DJ).
removeJobFromQueueUponRevokation(J, double, boolean) to initiate the revocation
(note that we cannot directly invoke AbstractSimQueue.revoke(double, J, boolean) or AbstractSimQueue.autoRevoke(double, J) on the composite queue
as that would trigger an incorrect revocation notification).
removeJobFromQueueUponDrop in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The job that is to be dropped.time - The current time (i.e., drop time of the job).IllegalStateException - If the real or delegate job does not exits.AbstractSimQueue.drop(J, double),
rescheduleAfterDrop(J, double),
removeJobFromQueueUponRevokation(J, double, boolean),
AbstractSimQueueComposite.removeJobsFromQueueLocal(J, DJ),
AbstractSimQueueComposite.getDelegateJob(SimJob),
SimJob.getQueue()protected final void rescheduleAfterDrop(J job, double time)
rescheduleAfterDrop in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The jobs that was dropped.time - The current time (i.e., drop time of the job).removeJobFromQueueUponDrop(J, double),
rescheduleAfterRevokation(J, double, boolean)protected final void removeJobFromQueueUponRevokation(J job, double time, boolean auto)
This method interacts delicately with rescheduleAfterRevokation(J, double, boolean)
and the MultiSimQueueNotificationProcessor on the sub-queues,
through the use of a pending revocation event (a local private field).
In a CTandem2, revocations on real jobs can occur either
through external requests, in other words, through AbstractSimQueue.revoke(double, J, boolean),
or because of auto-revocations
on the composite (this) queue through AbstractSimQueue.autoRevoke(double, J).
The delegate job is still present on a sub-queue, and we have to forcibly revoke it.
Because we cannot perform the revocation here (we are not allowed to reschedule!),
we defer until removeJobFromQueueUponRevokation(J, double, boolean) by raising an internal flag
(in fact a newly created, though not scheduled SimJQEvent.Revocation).
We have to use this method in order to remember the delegate job to be revoked,
and the queue from which to revoke it,
both of which are wiped from the internal administration by AbstractSimQueueComposite.removeJobsFromQueueLocal(J, DJ),
which is invoked last.
Note that even though a SimJQEvent.Revocation is used internally to flag the
required delegate-job revocation, it is never actually scheduled on the event list!
removeJobFromQueueUponRevokation in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The job that is to be revoked.time - The current time (i.e., revocation time of the job).auto - Whether or not this applies to an auto-revocation.IllegalStateException - If the delegate job is not visiting a sub-queue,
or if a pending delegate revocation has already been flagged (or been forgotten to clear).AbstractSimQueue.revoke(double, J, boolean),
AbstractSimQueue.autoRevoke(double, J),
SimJQEvent.Revocation,
rescheduleAfterRevokation(J, double, boolean),
AbstractSimQueueComposite.getDelegateJob(SimJob),
SimJob.getQueue(),
AbstractSimQueueComposite.removeJobsFromQueueLocal(J, DJ)protected final void rescheduleAfterRevokation(J job, double time, boolean auto)
This method interacts delicately with removeJobFromQueueUponRevokation(J, double, boolean)
and the MultiSimQueueNotificationProcessor on the sub-queues,
through the use of a pending revocation event (a local private field).
Upon return, the pending revocation event has been reset to null.
rescheduleAfterRevokation in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The jobs that was successfully revoked.time - The current time (i.e., revocation time of the job).auto - Whether or not this applies to an auto-revocation.IllegalStateException - If no pending delegate revocation was found,
or revoking the delegate job failed
(as indicated by the failure to reset the pending revocation event by the
sub-queue notification processor, see processSubQueueNotifications(java.util.List<org.javades.jqueues.r5.listener.MultiSimQueueNotificationProcessor.Notification<DJ, DQ>>)).
Note that even though a SimJQEvent.Revocation is used internally to flag the
required delegate-job revocation, it is never actually scheduled on the event list!
SimJQEvent.Revocation,
removeJobFromQueueUponRevokation(J, double, boolean),
processSubQueueNotifications(java.util.List<org.javades.jqueues.r5.listener.MultiSimQueueNotificationProcessor.Notification<DJ, DQ>>)protected final void setServerAccessCreditsSubClass()
This method sets the server-access credits on the wait queue
only if we run out of local server-access credits.
Note that the case in which we regain them is dealt with by rescheduleForNewServerAccessCredits(double).
setServerAccessCreditsSubClass in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>AbstractSimQueue.getServerAccessCredits(),
setServerAccessCreditsOnWaitQueue(),
rescheduleForNewServerAccessCredits(double)protected final void rescheduleForNewServerAccessCredits(double time)
This method sets the server-access credits on the wait queue.
Note that the case in which we lose them is dealt with by setServerAccessCreditsSubClass().
rescheduleForNewServerAccessCredits in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>time - The current time (i.e., the time at which new server-access credits became available).setServerAccessCreditsOnWaitQueue(),
setServerAccessCreditsSubClass()protected final void insertJobInQueueUponStart(J job, double time)
insertJobInQueueUponStart in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The job that starts.time - The current time (i.e., start time of the job).IllegalStateException - If sanity checks on internal consistency fail.AbstractSimQueue.isJob(org.javades.jqueues.r5.entity.jq.job.SimJob),
AbstractSimQueue.isJobInServiceArea(org.javades.jqueues.r5.entity.jq.job.SimJob),
rescheduleAfterStart(J, double)protected final void rescheduleAfterStart(J job, double time)
rescheduleAfterStart in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>job - The job that started (and is already present in AbstractSimQueue.getJobsInServiceArea().time - The current time (i.e., the start time of the job).IllegalStateException - If sanity checks on internal consistency fail.AbstractSimQueue.isJob(org.javades.jqueues.r5.entity.jq.job.SimJob),
AbstractSimQueue.isJobInServiceArea(org.javades.jqueues.r5.entity.jq.job.SimJob),
AbstractSimQueueComposite.getDelegateJob(J),
SimQueue.arrive(double, J),
insertJobInQueueUponStart(J, double)protected final void removeJobFromQueueUponDeparture(J departingJob, double time)
In the CTandem2,
a (real) job can only depart because of one of the following two reasons:
processSubQueueNotifications(java.util.List<org.javades.jqueues.r5.listener.MultiSimQueueNotificationProcessor.Notification<DJ, DQ>>).
In this case,
the delegate job has already left the sub-queue system when we are called,
hence no action is required to remove it from there.
All we have to do is invoke AbstractSimQueueComposite.removeJobsFromQueueLocal(J, DJ).
removeJobFromQueueUponRevokation(J, double, boolean) to initiate the revocation
(note that we cannot directly invoke AbstractSimQueue.revoke(double, J, boolean) or AbstractSimQueue.autoRevoke(double, J) on the composite queue
as that would trigger an incorrect revocation notification).
removeJobFromQueueUponDeparture in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>departingJob - The job that departs.time - The departure (current) time.IllegalStateException - If the real or delegate job does not exits.AbstractSimQueue.depart(double, J),
rescheduleAfterDeparture(J, double),
removeJobFromQueueUponRevokation(J, double, boolean),
AbstractSimQueueComposite.removeJobsFromQueueLocal(J, DJ),
AbstractSimQueueComposite.getDelegateJob(SimJob),
SimJob.getQueue()protected final void rescheduleAfterDeparture(J departedJob, double time)
rescheduleAfterDeparture in class AbstractSimQueue<J extends SimJob,Q extends CTandem2>departedJob - The departed job.time - The departure (current) time.removeJobFromQueueUponDeparture(J, double),
rescheduleAfterRevokation(J, double, boolean)protected final void processSubQueueNotifications(List<MultiSimQueueNotificationProcessor.Notification<DJ,DQ>> notifications)
Core method for reacting to SimEntityListener.notifyStateChanged(double, org.javades.jqueues.r5.entity.SimEntity, java.util.List<java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>>) notifications from all sub-queues.
This method is registered as the processor for an anonymous MultiSimQueueNotificationProcessor
(for all sub-queues) created upon construction,
see MultiSimQueueNotificationProcessor.Processor
and MultiSimQueueNotificationProcessor.setProcessor(org.javades.jqueues.r5.listener.MultiSimQueueNotificationProcessor.Processor).
This method takes one notification at a time, starting at the head of the list, removes it, and processes the notification as described below. While processing, new notifications may be added to the list; the list is processed until it is empty.
However, before processing any event, it checks for SimEntitySimpleEventType.RESET
(sub-)notifications. If it finds any, the notifications list is cleared and immediate return from this method follows.
A reset event, however, is subjected to rigorous sanity checks; notably, it has to be an isolated atomic event.
Failure of the sanity checks will lead to an IllegalStateException.
Otherwise, this method processes the notifications as described below;
the remainder of the method is encapsulated in a
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked() and AbstractSimEntity.fireAndLockPendingNotifications() pair,
to make sure we create atomic notifications in case of a top-level event.
We check that SimJQSimpleEventType.START and SimJQSimpleEventType.AUTO_REVOCATION
always come in pairs from the wait queue
and allow at most one such pair in a (atomic) notification.
A notification consists of a (fixed) sequence of sub-notifications,
see MultiSimQueueNotificationProcessor.Notification.getSubNotifications(),
each of which is processed in turn as follows:
SimEntitySimpleEventType.RESET, impossible, see above; throws an IllegalStateException.
SimQueueSimpleEventType.QUEUE_ACCESS_VACATION,
SimQueueSimpleEventType.QAV_START,
SimQueueSimpleEventType.QAV_END,
we throw an IllegalStateException.
SimQueueSimpleEventType.SERVER_ACCESS_CREDITS,
SimQueueSimpleEventType.REGAINED_SAC,
SimQueueSimpleEventType.OUT_OF_SAC,
as these are dealt with (if at all) by the outer loop.
SimQueueSimpleEventType.STA_FALSE,
SimQueueSimpleEventType.STA_TRUE,
as these are dealt with (if at all) by the outer loop.
SimJQSimpleEventType.ARRIVAL.
SimJQSimpleEventType.DROP, we drop the real job through AbstractSimQueue.drop(J, double).
SimJQSimpleEventType.REVOCATION, we check for the presence of a corresponding real job through
AbstractSimQueueComposite.getRealJob(DJ, DQ), and throw an IllegalStateException
if we found one. Revocation notifications must always be the result
of the composite queue's AbstractSimQueue.revoke(double, J, boolean) operation, and at this stage,
the real job has already been removed from the composite queue.
Subsequently, we perform sanity checks on the pending revocation event,
again throwing an IllegalStateException in case of an error.
If all is well, we simply clear the pending revocation event
on the composite queue.
SimJQSimpleEventType.AUTO_REVOCATION, we first check the source queue (must be the wait, or first, queue),
and throw an exception if the check fails.
Subsequently, we start the real job with AbstractSimQueue.start(double, J).
SimJQSimpleEventType.START, we do nothing.
SimJQSimpleEventType.DEPARTURE, we invoke AbstractSimQueueComposite.selectNextQueue(double, J, DQ) on the real job,
and let the delegate job arrive at the next queue if provided,
or makes the real job depart if not through AbstractSimQueue.depart(double, J).
After all sub-notifications have been processed,
we make sure the server-access credits on the wait queue are set properly with setServerAccessCreditsOnWaitQueue(),
unless the notification was a (single) SimEntitySimpleEventType.RESET,
and we can rely on the composite queue reset logic.
After all notifications have been processed, and the notification list is empty,
we invoke AbstractSimQueue.triggerPotentialNewStartArmed(double) on the composite queue,
in order to make sure we are not missing an autonomous change in SimQueue.isStartArmed()
on a sub-queue.
Since we do not expect any back-fire notifications from sub-queues from that method,
we check again the notification list, and throw an exception if it is non-empty.
A full description of the sanity checks would make this entry uninterestingly large(r), hence we refer to the source code. Most checks are trivial checks on the allowed sub-notifications from the sub-queues depending on the start model and on the presence or absence of real and delegate jobs (and their expected presence or absence on a sub-queue).
processSubQueueNotifications in class AbstractSimQueueComposite<DJ extends SimJob,DQ extends SimQueue,J extends SimJob,Q extends CTandem2>notifications - The sub-queue notifications, will be modified; empty upon return.IllegalArgumentException - If the list is null or empty, or contains a notification from another queue
than the a sub-queue,
or if other sanity checks fail.MultiSimQueueNotificationProcessor,
MultiSimQueueNotificationProcessor.Processor,
MultiSimQueueNotificationProcessor.setProcessor(org.javades.jqueues.r5.listener.MultiSimQueueNotificationProcessor.Processor),
SimEntitySimpleEventType.RESET,
SimJQSimpleEventType.ARRIVAL,
SimQueueSimpleEventType.QUEUE_ACCESS_VACATION,
SimQueueSimpleEventType.QAV_START,
SimQueueSimpleEventType.QAV_END,
SimQueueSimpleEventType.SERVER_ACCESS_CREDITS,
SimQueueSimpleEventType.OUT_OF_SAC,
SimQueueSimpleEventType.REGAINED_SAC,
SimQueueSimpleEventType.STA_FALSE,
SimQueueSimpleEventType.STA_TRUE,
SimJQSimpleEventType.DROP,
SimJQSimpleEventType.REVOCATION,
SimJQSimpleEventType.AUTO_REVOCATION,
SimJQSimpleEventType.START,
SimJQSimpleEventType.DEPARTURE,
AbstractSimEntity.addPendingNotification(java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>),
SimQueue.arrive(double, J),
AbstractSimQueue.start(double, J),
AbstractSimQueueComposite.selectNextQueue(double, J, DQ),
AbstractSimQueue.depart(double, J),
setServerAccessCreditsOnWaitQueue(),
AbstractSimQueue.triggerPotentialNewStartArmed(double),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.fireAndLockPendingNotifications()Copyright © 2018. All rights reserved.