/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.transport;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.context.Lifecycle;
import com.opengamma.util.MdcAwareThreadPoolExecutor;
import com.opengamma.util.NamedThreadPoolFactory;
/**
* Constructs a number of threads which each will dispatch byte array requests.
* Can be used as a simple way of multithreading request receivers.
*/
public class InMemoryQueueByteArrayRequestConduit implements Lifecycle, ByteArrayRequestSender {
private class DispatchJob implements Runnable {
private final byte[] _requestMessage;
private final ByteArrayMessageReceiver _responseReceiver;
public DispatchJob(byte[] requestMessage, ByteArrayMessageReceiver responseReceiver) {
_requestMessage = requestMessage;
_responseReceiver = responseReceiver;
}
/**
* @return the requestMessage
*/
public byte[] getRequestMessage() {
return _requestMessage;
}
/**
* @return the responseReceiver
*/
public ByteArrayMessageReceiver getResponseReceiver() {
return _responseReceiver;
}
@Override
public void run() {
byte[] response = getUnderlying().requestReceived(getRequestMessage());
getResponseReceiver().messageReceived(response);
}
}
private final AtomicBoolean _started = new AtomicBoolean(false);
private final ByteArrayRequestReceiver _underlying;
private final ExecutorService _executor;
private final boolean _localExecutor;
public InMemoryQueueByteArrayRequestConduit(int nWorkerThreads, ByteArrayRequestReceiver underlying) {
_underlying = underlying;
ThreadFactory tf = new NamedThreadPoolFactory("InMemoryQueueByteArrayRequestConduit", true);
ThreadPoolExecutor executor = new MdcAwareThreadPoolExecutor(
0, nWorkerThreads, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), tf);
_executor = executor;
_localExecutor = true;
}
public InMemoryQueueByteArrayRequestConduit(ExecutorService executor, ByteArrayRequestReceiver underlying) {
_underlying = underlying;
_executor = executor;
_localExecutor = false;
}
/**
* @return the underlying
*/
public ByteArrayRequestReceiver getUnderlying() {
return _underlying;
}
/**
* @return the executor
*/
public ExecutorService getExecutor() {
return _executor;
}
@Override
public void sendRequest(byte[] request,
ByteArrayMessageReceiver responseReceiver) {
getExecutor().execute(new DispatchJob(request, responseReceiver));
}
@Override
public boolean isRunning() {
return _started.get();
}
@Override
public synchronized void start() {
_started.set(true);
}
@Override
public synchronized void stop() {
if (!isRunning()) {
return;
}
if (_localExecutor) {
getExecutor().shutdown();
try {
getExecutor().awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
_started.set(false);
}
}