public abstract class AbstractSimQueue<J extends SimJob,Q extends AbstractSimQueue> extends AbstractSimJQ<J,Q> implements SimQueue<J,Q>
SimQueue.
The abstract base class takes care of maintaining
the job queue getJobs(),
the jobs in the waiting area getJobsInWaitingArea()
and the jobs in the service area getJobsInServiceArea().
It provides final implementations of all SimQueue's internal
and external operation,
delegating when needed to (simpler) abstract operation-specific methods
to be implemented by sub-classes.
XXX A bit more explanation would be nice here...
Copyright (C) 2005-2017 Jan de Jongh, TNO
This file is covered by the LICENSE file in the root of this project.
AbstractSimEntity.Notifier, AbstractSimEntity.PreNotificationHookSimQueue.AutoRevocationPolicySimEntity.Action, SimEntity.UnknownNotificationTypePolicy, SimEntity.UnknownOperationPolicy| Modifier and Type | Field and Description |
|---|---|
protected Set<org.javades.jsimulation.r5.SimEvent> |
eventsScheduled
Events scheduled on behalf of this
SimQueue. |
protected static boolean |
SANITY
When
false, this class and some sub-classes skip several (not all) sanity checks. |
USE_ARRAY_OPTIMIZATION| Modifier | Constructor and Description |
|---|---|
protected |
AbstractSimQueue(org.javades.jsimulation.r5.SimEventList eventList)
Creates an abstract queue given an event list.
|
| Modifier and Type | Method and Description |
|---|---|
void |
arrive(double time,
J job)
Handles an arrival at this queue.
|
protected void |
autoRevoke(double time,
J job)
Auto-revokes a job at this queue.
|
protected void |
cancelDepartureEvent(J job)
Cancels a pending departure event for given job on the event list.
|
protected void |
cancelDepartureEvent(SimJQEvent.Departure<J,Q> event)
Cancels a pending departure event on the event list.
|
protected void |
depart(double time,
J job)
Departure (unconditionally) of a job (for subclass and departure-event use).
|
protected void |
departureFromEventList(SimJQEvent.Departure<J,Q> event)
Deals with a departure event from the event list (for internal use only).
|
protected void |
drop(J job,
double time)
Drops a job from this queue, on the queue's initiative.
|
SimQueue.AutoRevocationPolicy |
getAutoRevocationPolicy()
Gets the auto-revocation policy of this queue.
|
protected Set<SimJQEvent.Departure> |
getDepartureEvents()
Gets all departure events.
|
protected Set<SimJQEvent.Departure> |
getDepartureEvents(J job)
Gets all departure events for given job.
|
protected J |
getFirstJob()
Returns the first job in
getJobs() (earliest arriver) . |
protected J |
getFirstJobInServiceArea()
Returns the first job in
getJobsInServiceArea() (earliest starter). |
protected J |
getFirstJobInWaitingArea()
Returns the first job in
getJobsInWaitingArea() (earliest waiting arriver) . |
Set<J> |
getJobs()
Gets the set of jobs currently visiting this queue.
|
Set<J> |
getJobsInServiceArea()
Get the set of jobs in the service area.
|
Set<J> |
getJobsInWaitingArea()
Get the set of jobs in the waiting area.
|
int |
getNumberOfJobs()
Gets the number of jobs currently visiting the queue.
|
int |
getNumberOfJobsInServiceArea()
Gets the number of jobs in the service area.
|
int |
getNumberOfJobsInWaitingArea()
Gets the number of jobs in the waiting area.
|
int |
getServerAccessCredits()
Gets the (remaining) server-access credits.
|
protected double |
getServiceTimeForJob(J job)
Returns the service time for a job at this queue.
|
protected boolean |
hasJobs()
Returns whether this queue has jobs present.
|
protected boolean |
hasJobsInServiceArea()
Returns whether or not this queue has at least one job in the service area.
|
protected boolean |
hasJobsInWaitingArea()
Returns whether or not this queue has at least one job waiting.
|
protected boolean |
hasServerAcccessCredits()
Returns
true if this queue has server-access credits left. |
protected abstract void |
insertJobInQueueUponArrival(J job,
double time)
Inserts a job that just arrived (at given time) into sub-class specific administration.
|
protected abstract void |
insertJobInQueueUponStart(J job,
double time)
Updates the internal subclass-specific data structures upon the start of a job.
|
boolean |
isJob(SimJob job)
Checks for the presence of a job.
|
boolean |
isJobInServiceArea(SimJob job)
Checks for the presence of a job in the service area.
|
boolean |
isJobInWaitingArea(SimJob job)
Checks for the presence of a job in the waiting area.
|
boolean |
isQueueAccessVacation()
Returns whether or not this queue is on queue-access vacation (from an internal flag).
|
protected void |
queueAccessVacationDropSubClass(double time,
J job)
Specific sub-class handling upon job-drop events due to queue-access vacations.
|
void |
registerStdOutSimQueueListener()
Registers the (private)
StdOutSimQueueListener as listener (convenience method). |
protected abstract void |
removeJobFromQueueUponDeparture(J departingJob,
double time)
Removes a job from the internal queues upon departure.
|
protected abstract void |
removeJobFromQueueUponDrop(J job,
double time)
Removes a job from the internal subclass administration because it is to be dropped.
|
protected abstract void |
removeJobFromQueueUponRevokation(J job,
double time,
boolean auto)
Removes a job from the internal sub-class administration since it is revoked.
|
protected abstract void |
rescheduleAfterArrival(J job,
double time)
Reschedules after a job arrival.
|
protected abstract void |
rescheduleAfterDeparture(J departedJob,
double time)
Reschedules if needed after a job departure has been effectuated by the base class.
|
protected abstract void |
rescheduleAfterDrop(J job,
double time)
Reschedules if needed after a job has been dropped from this queue.
|
protected abstract void |
rescheduleAfterRevokation(J job,
double time,
boolean auto)
Reschedules if needed after a job has been revoked from this queue.
|
protected abstract void |
rescheduleAfterStart(J job,
double time)
Reschedules after a job start.
|
protected abstract void |
rescheduleForNewServerAccessCredits(double time)
Reschedules if needed due to the (new) availability of server-access credits.
|
protected void |
resetEntitySubClass()
Invokes super method, removes all jobs without notifications,
ends all vacations, restores the number of server-access credits (to infinity)
and resets all caches.
|
void |
revoke(double time,
J job)
Calls super method on
SimQueue (and makes it final). |
boolean |
revoke(double time,
J job,
boolean interruptService)
Revokes a job from this queue.
|
protected SimJQEvent.Departure<J,Q> |
scheduleDepartureEvent(double time,
J job)
Schedules a suitable
SimEvent for a job's future departure on the event list. |
void |
scheduleJobArrival(double time,
J job)
Schedules a job arrival at this
AbstractSimQueue on its SimEventList. |
void |
setAutoRevocationPolicy(SimQueue.AutoRevocationPolicy autoRevocationPolicy)
Sets the auto-revocation policy of this queue.
|
void |
setQueueAccessVacation(double time,
boolean start)
Starts or ends a queue-access vacation.
|
void |
setServerAccessCredits(double time,
int credits)
Sets the remaining number of server-access credits.
|
protected void |
setServerAccessCreditsSubClass()
Notifies subclasses of a new externally-set value for the server-access credits through
setServerAccessCredits(double, int). |
protected void |
start(double time,
J job)
Starts a job at this queue, unconditionally (for subclass use).
|
protected void |
takeServerAccessCredit()
Takes a single server-access credit, which must be available (for subclass use).
|
String |
toStringDefault()
Returns "AbstractSimQueue".
|
protected void |
triggerPotentialNewStartArmed(double time)
Triggers a potential, autonomous (top-level) change in the
SimQueue.isStartArmed() status (for sub-class use). |
void |
unregisterStdOutSimQueueListener()
Unregisters the (private)
StdOutSimQueueListener as listener, if registered (convenience method). |
addPendingNotification, 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, waitgetCopySimQueue, isStartArmeddoAfterNotifications, doOperation, getEventList, getLastUpdateTime, getRegisteredNotificationTypes, getRegisteredOperations, getSimEntityListeners, getUnknownNotificationTypePolicy, getUnknownOperationPolicy, isIgnoreEventListReset, registerSimEntityListener, resetEntity, setIgnoreEventListReset, setName, setUnknownNotificationTypePolicy, setUnknownOperationPolicy, unregisterSimEntityListener, updatenotifyEventListResetgetQoS, getQoSClassprotected static final boolean SANITY
false, this class and some sub-classes skip several (not all) sanity checks.protected final Set<org.javades.jsimulation.r5.SimEvent> eventsScheduled
SimQueue.
Any events in this set must also be in the AbstractSimEntity.eventList.protected AbstractSimQueue(org.javades.jsimulation.r5.SimEventList eventList)
eventList - The event list to use.IllegalArgumentException - If the event list is null.public String toStringDefault()
toStringDefault in interface SimEntitytoStringDefault in class AbstractSimEntitySimEntity.setName(java.lang.String),
Object.toString()public final void registerStdOutSimQueueListener()
StdOutSimQueueListener as listener (convenience method).public final void unregisterStdOutSimQueueListener()
StdOutSimQueueListener as listener, if registered (convenience method).public final SimQueue.AutoRevocationPolicy getAutoRevocationPolicy()
SimQueuegetAutoRevocationPolicy in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>SimQueue.AutoRevocationPolicypublic final void setAutoRevocationPolicy(SimQueue.AutoRevocationPolicy autoRevocationPolicy)
SimQueueThe auto-revocation policy on a queue should be set only once and before the queue's use. It must survive queue resets.
setAutoRevocationPolicy in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>autoRevocationPolicy - The new auto-revocation policy, non-null.SimQueue.AutoRevocationPolicypublic final Set<J> getJobs()
SimQueuegetJobs in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>null.SimQueue.getNumberOfJobs(),
SimQueue.getJobsInWaitingArea(),
SimQueue.getJobsInServiceArea()public final int getNumberOfJobs()
SimQueue
Typically, this method is more efficient than getJobs ().size (),
but both methods must always yield the same result.
getNumberOfJobs in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>SimQueue.getJobs(),
SimQueue.getNumberOfJobsInWaitingArea(),
SimQueue.getNumberOfJobsInServiceArea()public final boolean isJob(SimJob job)
SimQueue
Typically, this method is more efficient than getJobs ().contains (job),
but both methods must always yield the same result.
isJob in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>job - The job.SimQueue.getJobs()protected final boolean hasJobs()
Functionally equivalent to getNumberOfJobs () == 0.
getNumberOfJobs()protected final J getFirstJob()
getJobs() (earliest arriver) .getJobs(),
i.e., the one with the earliest arrival time;
null if there are no jobs.public final Set<J> getJobsInWaitingArea()
SimQueuegetJobsInWaitingArea in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>null.SimQueue.getNumberOfJobsInWaitingArea(),
SimQueue.getJobs(),
SimQueue.getJobsInServiceArea()public final int getNumberOfJobsInWaitingArea()
SimQueue
Typically, this method is more efficient than getJobsInWaitingArea ().size (),
but both methods must always yield the same result.
getNumberOfJobsInWaitingArea in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>SimQueue.getJobsInWaitingArea(),
SimQueue.getNumberOfJobs(),
SimQueue.getNumberOfJobsInServiceArea()public final boolean isJobInWaitingArea(SimJob job)
SimQueue
Typically, this method is more efficient than getJobsInWaitingArea ().contains (job),
but both methods must always yield the same result.
isJobInWaitingArea in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>job - The job.SimQueue.getJobsInWaitingArea()protected final boolean hasJobsInWaitingArea()
Functionally equivalent to getNumberOfJobsInWaitingArea () == 0.
getNumberOfJobsInWaitingArea()protected final J getFirstJobInWaitingArea()
getJobsInWaitingArea() (earliest waiting arriver) .getJobsInWaitingArea(),
i.e., the one with the earliest arrival time;
null if there are no waiting jobs.public final Set<J> getJobsInServiceArea()
SimQueuegetJobsInServiceArea in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>null.SimQueue.getNumberOfJobsInServiceArea(),
SimQueue.getJobs(),
SimQueue.getJobsInWaitingArea()public final int getNumberOfJobsInServiceArea()
SimQueue
Typically, this method is more efficient than getJobsInServiceArea ().size (),
but both methods must always yield the same result.
getNumberOfJobsInServiceArea in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>SimQueue.getJobsInServiceArea(),
SimQueue.getNumberOfJobs(),
SimQueue.getNumberOfJobsInWaitingArea()public final boolean isJobInServiceArea(SimJob job)
SimQueue
Typically, this method is more efficient than getJobsInServiceArea ().contains (job),
but both methods must always yield the same result.
isJobInServiceArea in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>job - The job.SimQueue.getJobsInWaitingArea()protected final boolean hasJobsInServiceArea()
Functionally equivalent to getNumberOfJobsInServiceArea () == 0.
getNumberOfJobsInServiceArea()protected final J getFirstJobInServiceArea()
getJobsInServiceArea() (earliest starter).getJobsInServiceArea(),
i.e., the one with the earliest start time;
null if there are no jobs in the service area.protected void resetEntitySubClass()
resetEntitySubClass in class AbstractSimJQ<J extends SimJob,Q extends AbstractSimQueue>SimEntity.resetEntity()protected final void triggerPotentialNewStartArmed(double time)
SimQueue.isStartArmed() status (for sub-class use).
In most cases, a change in the SimQueue.isStartArmed() state will be the result of operations in this SimQueue,
and will be noted and reported automatically
through the use of the pre-notification hook startArmedPreNotificationHook(java.util.List<java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>>).
It is, however, perfectly legal that the SimQueue.isStartArmed() state of a SimQueue
changes independently from external or other monitored internal events.
Concrete subclasses must therefore invoke this method upon suspected autonomous changes in the SimQueue.isStartArmed() state,
in order to make sure that they are properly notified to listeners.
The implementation checks if the current SimQueue.isStartArmed() state is different from the cached value
as maintained by startArmedPreNotificationHook(java.util.List<java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>>).
If so, and if it is a top-level event, as assessed with AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
it invokes AbstractSimEntity.update(double), adds and fires a proper notification, i.c.,
SimQueueSimpleEventType.STA_TRUE or
SimQueueSimpleEventType.STA_FALSE,
and fires a notification through AbstractSimEntity.fireAndLockPendingNotifications().
In all other cases, this method does nothing,
relying on the pre-notification hook startArmedPreNotificationHook(java.util.List<java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>>).
time - The current time.AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
SimQueue.isStartArmed(),
AbstractSimEntity.update(double),
AbstractSimEntity.addPendingNotification(java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>),
SimQueueSimpleEventType.STA_TRUE,
SimQueueSimpleEventType.STA_FALSE,
AbstractSimEntity.fireAndLockPendingNotifications()public final void arrive(double time,
J job)
This (final) implementation is as described below.
It first makes sanity checks (e.g., job not already present).
It then invokes AbstractSimEntity.update(double)
and AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
insisting to be a top-level event (at the expense of an IllegalStateException),
and adds a SimJQSimpleEventType.ARRIVAL pending notification.
Subsequently, if the queue is on queue-access vacation (isQueueAccessVacation),
it adds a SimJQSimpleEventType.DROP pending notification; bypassing drop(J, double)
since subclasses have no knowledge of the job yet (and they do not need to have),
and invokes queueAccessVacationDropSubClass(double, J).
The latter method allows for (the rare case of) specific sub-class handling.
Otherwise, it then invokes the subclass-specific insertJobInQueueUponArrival(J, double),
adds the job to the job queue and to the waiting area,
set the job's queue property to this queue through SimJob.setQueue(Q),
and invokes the subclass-specific rescheduleAfterArrival(J, double).
Finally, it notifies listeners of the pending notifications.
arrive in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>time - The time at which the job arrives, i.c., the current time.job - The job.insertJobInQueueUponArrival(J, double),
rescheduleAfterArrival(J, double),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>),
AbstractSimEntity.fireAndLockPendingNotifications()protected abstract void insertJobInQueueUponArrival(J job, double time)
To be implemented by concrete queue types.
Implementations must ignore any queue-access vacation as this is taken care of already by the base class.
Implementations must not reschedule on the event list,
but instead wait for the imminent invocation of
rescheduleAfterArrival(J, double) for that.
Implementations should not set the queue on the job, as this is done by the base class.
See SimJob.setQueue(Q).
Implementations do no have to invoke AbstractSimEntity.update(double); this has been done already before the call to this method.
job - The job that arrived.time - The current time (i.e., arrival time of the job).arrive(double, J),
rescheduleAfterArrival(J, double)protected abstract void rescheduleAfterArrival(J job, double time)
The job has already been put into the internal data structures, and notifications are already pending for the
arrival. Also, it is guaranteed that there are no queue-access vacations, as these are being dealt with by the
base class, and AbstractSimEntity.update(double) has already been called.
Typically, but not necessarily, implementations must check whether or not to start the job immediately,
and invoke start(double, J) if so.
Implementations must not insert a SimJQSimpleEventType.ARRIVAL notification,
as this is already done by the base class AbstractSimQueue.
They must, however, add appropriate notifications for other internal state-changing events.
job - The job that arrived (and is already present in getJobs()).time - The current time (i.e., the arrival time of the job).arrive(double, J),
insertJobInQueueUponArrival(J, double)public final void scheduleJobArrival(double time,
J job)
time - The arrival time of the job, which must be in the future,
relative to both the last update time of this SimQueue as to the time on the event list.job - The job to arrive.IllegalArgumentException - If time is in the past, or job is null.arrive(double, J),
AbstractSimEntity.getLastUpdateTime(),
SimEventList.getTime()public final boolean isQueueAccessVacation()
Note that queue-access vacations are entirely dealt with by this base class AbstractSimQueue; there is
no interaction (needed) with concrete subclasses, but see queueAccessVacationDropSubClass(double, J).
isQueueAccessVacation in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>SimQueue.setQueueAccessVacation(double, boolean)public final void setQueueAccessVacation(double time,
boolean start)
This final implementation just sets the internal flag indicating a queue-access vacation or not.
The a-priori call to AbstractSimEntity.update(double) and the a-posteriori pending notification
of either SimQueueSimpleEventType.QAV_START or SimQueueSimpleEventType.QAV_END
are only effectuated if the vacation status queue actually changed.
This method insists to be a top-level event (at the expense of an IllegalStateException).
Note that queue-access vacations are entirely dealt with by the base class AbstractSimQueue; there is
no interaction (needed) with concrete subclasses, but see queueAccessVacationDropSubClass(double, J).
setQueueAccessVacation in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>time - The time at which to start or end the queue-access vacation, i.c., the current time.start - Whether to start (true) or end (false) the vacation.arrive(double, J),
queueAccessVacationDropSubClass(double, J),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>),
AbstractSimEntity.fireAndLockPendingNotifications()protected void queueAccessVacationDropSubClass(double time,
J job)
Normally, queue-access vacations, their effects on arriving jobs, as well as the required notifications
are entirely dealt with by this abstract class.
However, this current method is invoked from within arrive(double, J) when a job is dropped due to a queue-access vacation,
for instance, because the concrete sub-class needs to issue dedicated notifications
upon job-drops.
No changes to the state of this SimQueue should result from this method,
and no SimEvents should be scheduled or canceled.
The default implementation does nothing.
time - The time the job was dropped, i.e., the current time.job - The dropped job.arrive(double, J),
setQueueAccessVacation(double, boolean)protected final void drop(J job, double time)
This (final) implementation is as described below.
It first makes makes sanity checks (e.g., job present),
and assures that AbstractSimEntity.update(double) and AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked()
have been invoked by the caller (since this is an internal operation).
It invokes the subclass-specific removeJobFromQueueUponDrop(J, double),
removes the job from the internal administration,
sets the visited queue on the job (with SimJob.setQueue(Q)) to null,
and adds a SimJQSimpleEventType.DROP pending notification.
It then invokes the subclass-specific rescheduleAfterDrop(J, double).
This method does not notify listeners through AbstractSimEntity.fireAndLockPendingNotifications().
job - The job to be dropped.time - The current time, i.e., the drop time of the job.IllegalArgumentException - If the job is null or not found, or has its queue not set to this queue.IllegalStateException - If the internal administration of this queue has become inconsistent.removeJobFromQueueUponDrop(J, double),
rescheduleAfterDrop(J, double),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(SimEntitySimpleEventType.Member, SimEntityEvent),
AbstractSimEntity.fireAndLockPendingNotifications()protected abstract void removeJobFromQueueUponDrop(J job, double time)
To be implemented by concrete queue types.
Implementations must remove the job from their local administration, and remove any job-specific events (like a departure event) from the event-list.
Implementations must not reschedule events for other jobs on the event list,
but instead wait for the imminent invocation of
rescheduleAfterDrop(J, double) for that.
job - The job that is to be dropped.time - The current time (i.e., drop time of the job).drop(J, double),
rescheduleAfterDrop(J, double)protected abstract void rescheduleAfterDrop(J job, double time)
Implementations can rely on the fact that the job is no longer present in the internal data structures,
that it has no pending events on the event list,
and that this method is invoked immediately after removeJobFromQueueUponDrop(J, double).
Implementations must not insert a SimJQSimpleEventType.DROP notification,
as this is already done by the base class AbstractSimQueue.
They must, however, add appropriate notifications for other internal state-changing events.
job - The jobs that was dropped.time - The current time (i.e., drop time of the job).drop(J, double),
removeJobFromQueueUponDrop(J, double)public final boolean revoke(double time,
J job,
boolean interruptService)
This (final) implementation is as described below.
It first makes makes sanity checks (e.g., job is non-null).
It then checks whether the revocation is to be refused
which is the case when the job is not present, or has already been started and interruptService == false.
If revocation is to be refused, this method simple returns false.
Otherwise,
it invokes AbstractSimEntity.update(double)
and AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
insisting to be a top-level event (at the expense of an IllegalStateException).
It invokes the subclass-specific removeJobFromQueueUponRevokation(J, double, boolean),
removes the job from the internal administration,
sets the visited queue on the job (with SimJob.setQueue(Q)) to null,
and adds a SimJQSimpleEventType.REVOCATION pending notification.
It then invokes the subclass-specific rescheduleAfterRevokation(J, double, boolean).
Finally, it notifies listeners of the pending notifications.
revoke in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>time - The time at which the request is issued, i.c., the current time.job - The job to be revoked from the queue.interruptService - Whether to allow interruption of the job's
service if already started.
If false, revocation will only succeed if the
job has not started yet.false if the job is not present).SimJQSimpleEventType.REVOCATION,
removeJobFromQueueUponRevokation(J, double, boolean),
rescheduleAfterRevokation(J, double, boolean),
autoRevoke(double, J),
AbstractSimEntity.update(double),
AbstractSimEntity.getLastUpdateTime(),
SimJob.setQueue(Q),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(SimEntitySimpleEventType.Member, SimEntityEvent),
AbstractSimEntity.fireAndLockPendingNotifications()public final void revoke(double time,
J job)
SimQueue (and makes it final).revoke in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>time - The time at which the request is issued, i.c., the current time.job - The job to be revoked from the queue.SimQueue.revoke(double, SimJob, boolean)protected final void autoRevoke(double time,
J job)
The final implementation of this method is identical to that of revoke(double, J, boolean),
with the exceptions that
AbstractSimEntity.update(double) and AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked()
have been invoked by the caller (since this is an internal operation),
IllegalStateException),
SimJQSimpleEventType.AUTO_REVOCATION is added as pending notification
(instead of a SimJQSimpleEventType.REVOCATION),
AbstractSimEntity.fireAndLockPendingNotifications().
job - The job to be revoked.time - The current time, i.e., the auto-revocation time of the job.removeJobFromQueueUponRevokation(J, double, boolean),
rescheduleAfterRevokation(J, double, boolean),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(SimEntitySimpleEventType.Member, SimEntityEvent),
AbstractSimEntity.fireAndLockPendingNotifications()protected abstract void removeJobFromQueueUponRevokation(J job, double time, boolean auto)
To be implemented by concrete queue types.
This method is shared between revoke(double, J, boolean) and autoRevoke(double, J).
Implementations must remove the job from their local subclass-specific administration. They should also remove any job-specific events (like a departure event) from the event-list.
Implementations must not reschedule events for other jobs on the event list,
but instead wait for the imminent invocation of
rescheduleAfterRevokation(J, double, boolean) for that.
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.revoke(double, J, boolean),
autoRevoke(double, J),
rescheduleAfterRevokation(J, double, boolean),
SimQueue.AutoRevocationPolicyprotected abstract void rescheduleAfterRevokation(J job, double time, boolean auto)
This method is shared between revoke(double, J, boolean) and autoRevoke(double, J).
Implementations can rely on the fact that the job is no longer present in the internal data structures,
that it has no pending events on the event list,
and that this method is invoked immediately after a successful removeJobFromQueueUponRevokation(J, double, boolean).
Implementations must not insert a SimJQSimpleEventType.REVOCATION
or SimJQSimpleEventType.AUTO_REVOCATION notification,
as this is already done by the base class AbstractSimQueue.
They must, however, add appropriate notifications for other internal state-changing events.
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.revoke(double, J, boolean),
autoRevoke(double, J),
removeJobFromQueueUponRevokation(J, double, boolean),
SimQueue.AutoRevocationPolicypublic final int getServerAccessCredits()
SimQueue
The number of server-access credits is the remaining number of jobs allowed to start.
They play an essential role in composite queues, notably CTandem2.
Upon reset, the initial value must be Integer.MAX_VALUE,
which is treated as infinity.
getServerAccessCredits in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>Integer.MAX_VALUE treated as infinity.SimQueue.setServerAccessCredits(double, int)public final void setServerAccessCredits(double time,
int credits)
This final implementation invokes AbstractSimEntity.update(double) only if the number of credits passed in the argument differs from the
current number of credits, to serve statistics on the number of server-access credits.
The method does nothing if the number has not changed.
Otherwise, it updates the internal administration of the number of server-access credits.
It then checks whether we either lost server-access credits, or regained them,
and invokes rescheduleForNewServerAccessCredits(double) in the latter case,
and sets up the proper notification of listeners in both cases,
insisting to be a top-level event (at the expense of an IllegalStateException).
In any case (including a mere change of value of the server-access credits),
it then invokes setServerAccessCreditsSubClass() to notify interested subclasses
of the new value for the server-access-credits (but note that this value may have changed already due to rescheduling).
Note that the insertion of SimQueueSimpleEventType.OUT_OF_SAC
or SimQueueSimpleEventType.REGAINED_SAC if needed is picked up by a registered pre-notification hook;
see AbstractSimEntity.registerPreNotificationHook(org.javades.jqueues.r5.entity.AbstractSimEntity.PreNotificationHook).
setServerAccessCredits in interface SimQueue<J extends SimJob,Q extends AbstractSimQueue>time - The time at which to set the credits, i.c., the current time.credits - The new remaining server-access credits, non-negative, with Integer.MAX_VALUE treated as infinity.getServerAccessCredits(),
rescheduleForNewServerAccessCredits(double),
SimQueueSimpleEventType.OUT_OF_SAC,
SimQueueSimpleEventType.REGAINED_SACprotected final boolean hasServerAcccessCredits()
true if this queue has server-access credits left.True if this queue has server-access credits left.protected final void takeServerAccessCredit()
IllegalStateException if there are no server-access credits, in other words,
caller must check this first.IllegalStateException - If there are no server-access credits left upon entry.hasServerAcccessCredits(),
SimQueueSimpleEventType.OUT_OF_SACprotected abstract void rescheduleForNewServerAccessCredits(double time)
Implementations can rely on the availability of server-access credits.
Implementations must not insert server-access-credits notifications.
This is done by the base class AbstractSimQueue.
They must, however, add appropriate notifications for other internal state-changing events.
time - The current time (i.e., the time at which new server-access credits became available).setServerAccessCredits(double, int),
hasServerAcccessCredits()protected void setServerAccessCreditsSubClass()
setServerAccessCredits(double, int).
Typical implementations would not be very interested in the actual value of the server-access credits, as long as it is strictly positive and properly maintained by this abstract base class. Hence, changes to the actual server-access credits are only reported if the credits become zero (prohibiting the start of jobs), or become non-zero (allowing waiting jobs to start).
This method, however, allows subclasses to closely follow (and take action upon) the exact value of the server-access
credits if changed through setServerAccessCredits(double, int), i.e., changed by an external entity.
The method is called from setServerAccessCredits(double, int) after the new value has been effectuated into the internal
administration, rescheduling has taken place but (right) before any listeners have been notified.
Concrete implementations should not change the server-access-credits, obviously,
and should not reschedule
(but instead implement such required rescheduling in rescheduleForNewServerAccessCredits(double) to that purpose).
The default implementation does nothing.
protected final void start(double time,
J job)
This (final) implementation is as described below.
It first makes sanity checks (e.g., job present and not already started),
and assures that AbstractSimEntity.update(double) and AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked()
have been invoked by the caller (since this is an internal operation).
It then takes a server-access credit through takeServerAccessCredit(),
throwing a IllegalStateException if not credits are available.
If the auto-revocation policy is SimQueue.AutoRevocationPolicy.UPON_START,
it adds a SimJQSimpleEventType.START pending notification,
yet immediately revokes the job through autoRevoke(double, J).
Note that in this case, insertJobInQueueUponStart(J, double)
and rescheduleAfterStart(J, double) are not used at all!
Otherwise, it invokes the subclass-specific insertJobInQueueUponStart(J, double),
moves the job from the waiting to the service area,
adds a SimJQSimpleEventType.START pending notification
and invokes the subclass-specific rescheduleAfterStart(J, double).
This method does not notify listeners through AbstractSimEntity.fireAndLockPendingNotifications().
job - The job that is to be started.time - The current time (i.e., start time of the job).insertJobInQueueUponStart(J, double),
rescheduleAfterStart(J, double),
getAutoRevocationPolicy(),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(SimEntitySimpleEventType.Member, SimEntityEvent),
AbstractSimEntity.fireAndLockPendingNotifications()protected abstract void insertJobInQueueUponStart(J job, double time)
To be implemented by concrete queue types.
Implementations must not reschedule,
but instead wait for the imminent invocation of
rescheduleAfterStart(J, double) for that.
Implementations should not care about server-access credits or auto-revocation;
this is taken care of by start(double, J).
job - The job that starts.time - The current time (i.e., start time of the job).start(double, J),
rescheduleAfterStart(J, double)protected abstract void rescheduleAfterStart(J job, double time)
The job has already been put into the internal data structures, and notifications are already pending for the
start. Also, AbstractSimEntity.update(double) has already been called.
Upon return, the job may have left this AbstractSimQueue already,
but the caller then assumes that all appropriate notifications
are added (to the pending notifications) in this method.
Implementations must not insert a SimJQSimpleEventType.START notification,
as this is already done by the base class AbstractSimQueue.
They must, however, add appropriate notifications for other internal state-changing events.
Implementations should not care about server-access credits or auto-revocation;
this is taken care of by start(double, J).
job - The job that started (and is already present in getJobsInServiceArea().time - The current time (i.e., the start time of the job).start(double, J),
insertJobInQueueUponStart(J, double)protected double getServiceTimeForJob(J job)
Intended to be the core method for obtaining the service time of a job during a visit.
Implementations must always return a non-negative value.
Implementations must always return the same value prior to a single visit, and during the visit itself. This method can only change its return value immediately after a job visit.
Note that this base class does not use this method; it is for sub-class use.
Also note that certain queueing disciplines may not support the notion
of a job's service time, and thus completely ignore this method.
At the discretion of the implementation,
an UnsupportedOperationException may even the thrown then.
job - The job, non-null.UnsupportedOperationException - If the notion of the service time of a job is not supported by this queue type
(e.g., because it does not allow jobs to start).protected final void departureFromEventList(SimJQEvent.Departure<J,Q> event)
Do not invoke this method directly from sub-classes; it is meant to be invoked from a scheduled SimJQEvent.Departure.
This method (final) check the presence of the departure event in eventsScheduled,
throwing an exception if absent,
and removes the event from that collection.
It then invokes AbstractSimEntity.update(double) with the event time,
and AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
insisting to be a top-level event (at the expense of an IllegalStateException).
Finally, it grabs the time and job parameters from the event argument,
invokes depart(double, J),
and notifies listeners through AbstractSimEntity.fireAndLockPendingNotifications().
event - The departure event; must be non-null and present in eventsScheduled.eventsScheduled,
SimJQEvent.Departure,
scheduleDepartureEvent(double, J),
depart(double, J),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(SimEntitySimpleEventType.Member, SimEntityEvent),
AbstractSimEntity.fireAndLockPendingNotifications()protected final void depart(double time,
J job)
This (final) implementation is as described below.
It first makes makes sanity checks (e.g., job present),
and assures that AbstractSimEntity.update(double) and AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked()
have been invoked by the caller (since this is an internal operation).
XXX Update: the check for presence of the job has been removed after June/July AbstractSimQueue revamp.
It sets the visited queue on the job (with SimJob.setQueue(Q)) to null.
It invokes the subclass-specific removeJobFromQueueUponDeparture(J, double),
removes the job from the local administration,
sets the visited queue on the job (with SimJob.setQueue(Q)) to null,
and adds a SimJQSimpleEventType.DEPARTURE pending notification.
It then invokes the subclass-specific rescheduleAfterDeparture(J, double).
This method does not notify listeners through AbstractSimEntity.fireAndLockPendingNotifications().
Note that this method does not (attempt to) cancel a SimJQEvent.Departure
for the job, nor does it maintain eventsScheduled!
time - The departure time.job - The job that departs.removeJobFromQueueUponDeparture(J, double),
rescheduleAfterDeparture(J, double),
AbstractSimEntity.clearAndUnlockPendingNotificationsIfLocked(),
AbstractSimEntity.addPendingNotification(SimEntitySimpleEventType.Member, SimEntityEvent),
AbstractSimEntity.fireAndLockPendingNotifications()protected abstract void removeJobFromQueueUponDeparture(J departingJob, double time)
Implementations must (at least) remove the job from their internal administration. They should also remove any job-specific events (like a queue-specific departure event) from the event-list.
Implementations must not reschedule (e.g., events for other jobs on the event list),
but instead wait for the imminent invocation of
rescheduleAfterDeparture(J, double) for that.
Implementations must not fire departure events. This is done by the base class AbstractSimQueue.
departingJob - The job that departs.time - The departure (current) time.depart(double, J),
rescheduleAfterDeparture(J, double)protected abstract void rescheduleAfterDeparture(J departedJob, double time)
Implementations can rely on the fact that the job is no longer present in the internal data structures,
that it has no pending events on the event list,
and that this method is invoked immediately after removeJobFromQueueUponDeparture(J, double).
Implementations must not insert a SimJQSimpleEventType.DEPARTURE notification,
as this is already done by the base class AbstractSimQueue.
They must, however, add appropriate notifications for other internal state-changing events.
departedJob - The departed job.time - The departure (current) time.depart(double, J),
removeJobFromQueueUponDeparture(J, double)protected final SimJQEvent.Departure<J,Q> scheduleDepartureEvent(double time, J job)
SimEvent for a job's future departure on the event list.
The implementation requires passing several rigorous sanity checks,
after which it creates a new SimJQEvent.Departure,
adds it to eventsScheduled and schedules the new event on the event list.
Effectively, this ensures that unless the event is canceled,
the method departureFromEventList(org.javades.jqueues.r5.entity.jq.SimJQEvent.Departure<J, Q>) is invoked upon reaching the departure event.
The base class AbstractSimQueue does not use this method; it is provided as a service to subclasses.
time - The departure time.job - The job to depart.AbstractSimEntity.getEventList(),
AbstractSimEntity.getLastUpdateTime(),
SimJQEventScheduler.scheduleJQ(SimEventList, SimJQEvent)protected final void cancelDepartureEvent(SimJQEvent.Departure<J,Q> event)
After sanity checks on the event not being null,
and on the event's presence in AbstractSimEntity.getEventList() and eventsScheduled,
this method removes the event from the event list and from eventsScheduled.
XXX Check on presence of job currently deactivated.
The base class AbstractSimQueue does not use this method; it is provided as a service to subclasses.
event - The departure event to cancel, non-null.IllegalArgumentException - If the argument is null, or not present
in both AbstractSimEntity.getEventList() and eventsScheduled.eventsScheduled,
AbstractSimEntity.getEventList()protected final void cancelDepartureEvent(J job)
After several rigorous sanity checks, this default implementation
removes the event from the event list and from eventsScheduled.
Note that a unique SimJQEvent.Departure must be found in eventsScheduled for the job supplied,
otherwise a IllegalArgumentException is thrown.
The base class AbstractSimQueue does not use this method; it is provided as a service to subclasses.
job - The job for which the unique departure event to cancel.IllegalArgumentException - If zero or multiple SimJQEvent.Departures
were found for the job in eventsScheduled.eventsScheduled,
AbstractSimEntity.getEventList(),
getDepartureEvents()protected final Set<SimJQEvent.Departure> getDepartureEvents()
SimJQEvent.Departures in eventsScheduled.null Set holding all future departure events.protected final Set<SimJQEvent.Departure> getDepartureEvents(J job)
SimJQEvent.Departures for the given job in eventsScheduled.job - The job.null Set holding all scheduled departure events for the job.Copyright © 2018. All rights reserved.