/** * Only to be used by ProcedureScheduler implementations. * Reason: To wake up multiple events, locking sequence is * schedLock --> synchronized (event) * To wake up an event, both schedLock() and synchronized(event) are required. * The order is schedLock() --> synchronized(event) because when waking up multiple events * simultaneously, we keep the scheduler locked until all procedures suspended on these events * have been added back to the queue (Maybe it's not required? Evaluate!) * To avoid deadlocks, we want to keep the locking order same even when waking up single event. * That's why, {@link #wake(AbstractProcedureScheduler)} above uses the same code path as used * when waking up multiple events. * Access should remain package-private. */ @VisibleForTesting public synchronized void wakeInternal(AbstractProcedureScheduler procedureScheduler) { if (ready && !suspendedProcedures.isEmpty()) { LOG.warn("Found procedures suspended in a ready event! Size=" + suspendedProcedures.size()); } ready = true; if (LOG.isTraceEnabled()) { LOG.trace("Unsuspend " + toString()); } // wakeProcedure adds to the front of queue, so we start from last in the // waitQueue' queue, so that the procedure which was added first goes in the front for // the scheduler queue. procedureScheduler.addFront(suspendedProcedures.descendingIterator()); suspendedProcedures.clear(); }
@Override protected Procedure dequeue() { return runnables.poll(); }
public int wakeWaitingProcedures(ProcedureScheduler scheduler) { int count = queue.size(); // wakeProcedure adds to the front of queue, so we start from last in the waitQueue' queue, so // that the procedure which was added first goes in the front for the scheduler queue. scheduler.addFront(queue.descendingIterator()); queue.clear(); return count; }
@Override public boolean queueHasRunnables() { return runnables.size() > 0; }
/** * @return true if event is not ready and adds procedure to suspended queue, else returns false. */ public synchronized boolean suspendIfNotReady(Procedure proc) { if (!ready) { suspendedProcedures.addLast(proc); } return !ready; }
public boolean isEmpty() { return runnables.isEmpty(); }
@VisibleForTesting @Override public void clear() { schedLock(); try { runnables.clear(); } finally { schedUnlock(); } }
public int wakeWaitingProcedures(ProcedureScheduler scheduler) { int count = queue.size(); // wakeProcedure adds to the front of queue, so we start from last in the waitQueue' queue, so // that the procedure which was added first goes in the front for the scheduler queue. scheduler.addFront(queue.descendingIterator()); queue.clear(); return count; }
@Override public int queueSize() { return runnables.size(); }
public void addLast(Procedure<?> proc) { queue.addLast(proc); }
public boolean isWaitingQueueEmpty() { return queue.isEmpty(); }
@VisibleForTesting @Override public void clear() { schedLock(); try { runnables.clear(); } finally { schedUnlock(); } }
/** * Only to be used by ProcedureScheduler implementations. * Reason: To wake up multiple events, locking sequence is * schedLock --> synchronized (event) * To wake up an event, both schedLock() and synchronized(event) are required. * The order is schedLock() --> synchronized(event) because when waking up multiple events * simultaneously, we keep the scheduler locked until all procedures suspended on these events * have been added back to the queue (Maybe it's not required? Evaluate!) * To avoid deadlocks, we want to keep the locking order same even when waking up single event. * That's why, {@link #wake(AbstractProcedureScheduler)} above uses the same code path as used * when waking up multiple events. * Access should remain package-private. */ synchronized void wakeInternal(AbstractProcedureScheduler procedureScheduler) { if (ready && !suspendedProcedures.isEmpty()) { LOG.warn("Found procedures suspended in a ready event! Size=" + suspendedProcedures.size()); } ready = true; if (LOG.isTraceEnabled()) { LOG.trace("Unsuspend " + toString()); } // wakeProcedure adds to the front of queue, so we start from last in the // waitQueue' queue, so that the procedure which was added first goes in the front for // the scheduler queue. procedureScheduler.addFront(suspendedProcedures.descendingIterator()); suspendedProcedures.clear(); }
/** * Wakes up given waiting procedures by pushing them back into scheduler queues. * @return size of given {@code waitQueue}. */ protected int wakeWaitingProcedures(final ProcedureDeque waitQueue) { int count = waitQueue.size(); // wakeProcedure adds to the front of queue, so we start from last in the // waitQueue' queue, so that the procedure which was added first goes in the front for // the scheduler queue. addFront(waitQueue.descendingIterator()); waitQueue.clear(); return count; }
public int size() { return runnables.size(); }
/** * @return true if event is not ready and adds procedure to suspended queue, else returns false. */ public synchronized boolean suspendIfNotReady(Procedure proc) { if (!ready) { suspendedProcedures.addLast(proc); } return !ready; }
public Procedure<?> poll() { return runnables.poll(); }
public boolean isWaitingQueueEmpty() { return queue.isEmpty(); }