//
// ERLocalWorkerChannel.java
// Project ERWorkerChannel
//
// Created by tatsuya on Mon Jul 29 2002
//
package er.workerchannel;
import er.extensions.logging.ERXLogger;
public class ERLocalWorkerChannel implements ERWorkerChannel {
public static final ERXLogger log = ERXLogger.getERXLogger(ERLocalWorkerChannel.class);
private final int _queueSize;
private ERWorkUnit[] _workUnitQueue;
private int _head;
private int _tail;
private int _count;
private boolean _isSuspended;
private final ERWorkerThread[] _threadPool;
public ERLocalWorkerChannel(int numberOfThreads, int queueSize) {
_queueSize = queueSize;
_initalizeWorkUnitQueue();
_isSuspended = false;
_threadPool = new ERWorkerThread[numberOfThreads];
for (int i = 0; i < _threadPool.length; i++)
_threadPool[i] = new ERWorkerThread("Worker-" + i, this);
}
public void startWorkers() {
for (int i = 0; i < _threadPool.length; i++)
_threadPool[i].start();
}
public synchronized void shutdownWorkers() {
log.info("shutdownWorkers() - count = " + _count);
while (_count > 0) {
notifyAll();
try {
wait();
} catch (InterruptedException e) {
;
}
}
for (int i = 0; i < _threadPool.length; i++)
_threadPool[i].shutdown();
for (int i = 0; i < _threadPool.length; i++) {
notifyAll();
try {
_threadPool[i].join();
} catch (InterruptedException ex) {
;
}
}
}
public void suspendWorkers() {
_isSuspended = true;
}
public void resumeWorkers() {
_isSuspended = false;
notifyAll();
}
public synchronized ERResultUnit scheduleWorkUnit(ERWorkUnit workUnit) {
while (_count >= _workUnitQueue.length) {
try {
wait();
} catch (InterruptedException e) {
;
}
}
ERFutureResult futureResult = new ERFutureResult();
workUnit.setFutureResult(futureResult);
_workUnitQueue[_tail] = workUnit;
_tail = (_tail + 1) % _workUnitQueue.length;
_count++;
if (_count >= _queueSize * 0.15d)
notifyAll();
return futureResult;
}
public synchronized ERWorkUnit dispatchWorkUnit() {
while (_count <= 0 || _isSuspended) {
try {
wait();
} catch (InterruptedException e) {
;
}
}
ERWorkUnit workUnit = _workUnitQueue[_head];
_head = (_head + 1) % _workUnitQueue.length;
_count--;
if (_count <= _queueSize * (1.0d - 0.15d))
notifyAll();
return workUnit;
}
public synchronized void cancelScheduledWorkUnits() {
_initalizeWorkUnitQueue();
_isSuspended = false;
}
public int currentQueueSize() {
return _count;
}
private void _initalizeWorkUnitQueue() {
_workUnitQueue = new ERWorkUnit[_queueSize];
_head = 0;
_tail = 0;
_count = 0;
}
}