// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadCallable<T> {
// 	/**
// 	 * Performs the computation in MATLAB. The {@code proxy} provided will invoke its methods directly on MATLAB's
// 	 * main thread without delay. This {@code proxy} should be used to interact with MATLAB, not a
// 	 * {@code MatlabProxy} (or any class delegating to it).
// 	 * 
// 	 * @param proxy
// 	 * @return result of the computation
// 	 * @throws MatlabInvocationException
// 	 */
// 	public T call(MatlabThreadProxy proxy) throws MatlabInvocationException;
// }
// 
// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadProxy extends MatlabOperations {
// 
// }
// 
// Path: src/com/mathworks/jmi/Matlab.java
// public class Matlab {
// 	public static Object mtFevalConsoleOutput(String function, Object[] args, int nargout) throws Exception {
// 		throw new UnsupportedOperationException("stub");
// 	}
// 
// 	public static void whenMatlabIdle(Runnable runnable) {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }
// 
// Path: src/com/mathworks/jmi/NativeMatlab.java
// public class NativeMatlab {
// 	public static boolean nativeIsMatlabThread() {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }


import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import matlabcontrol.MatlabProxy.MatlabThreadCallable;
import matlabcontrol.MatlabProxy.MatlabThreadProxy;
import com.mathworks.jmi.Matlab;
import com.mathworks.jmi.NativeMatlab;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
			@Override
			public Void call(MatlabThreadProxy proxy) throws MatlabInvocationException {
				proxy.eval(command);

				return null;
			}
		});
	}

	static Object[] returningEval(final String command, final int nargout) throws MatlabInvocationException {
		return invokeAndWait(new MatlabThreadCallable<Object[]>() {
			@Override
			public Object[] call(MatlabThreadProxy proxy) throws MatlabInvocationException {
				return proxy.returningEval(command, nargout);
			}
		});
	}

	static void feval(final String functionName, final Object... args) throws MatlabInvocationException {
		invokeAndWait(new MatlabThreadCallable<Void>() {
			@Override
			public Void call(MatlabThreadProxy proxy) throws MatlabInvocationException {
				proxy.feval(functionName, args);

				return null;
			}
		});
	}

	static Object[] returningFeval(final String functionName, final int nargout, final Object... args)
// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadCallable<T> {
// 	/**
// 	 * Performs the computation in MATLAB. The {@code proxy} provided will invoke its methods directly on MATLAB's
// 	 * main thread without delay. This {@code proxy} should be used to interact with MATLAB, not a
// 	 * {@code MatlabProxy} (or any class delegating to it).
// 	 * 
// 	 * @param proxy
// 	 * @return result of the computation
// 	 * @throws MatlabInvocationException
// 	 */
// 	public T call(MatlabThreadProxy proxy) throws MatlabInvocationException;
// }
// 
// Path: src/matlabcontrol/MatlabProxy.java
// public static interface MatlabThreadProxy extends MatlabOperations {
// 
// }
// 
// Path: src/com/mathworks/jmi/Matlab.java
// public class Matlab {
// 	public static Object mtFevalConsoleOutput(String function, Object[] args, int nargout) throws Exception {
// 		throw new UnsupportedOperationException("stub");
// 	}
// 
// 	public static void whenMatlabIdle(Runnable runnable) {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }
// 
// Path: src/com/mathworks/jmi/NativeMatlab.java
// public class NativeMatlab {
// 	public static boolean nativeIsMatlabThread() {
// 		throw new UnsupportedOperationException("stub");
// 	}
// }


// Path: src/matlabcontrol/JMIWrapper.java
import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import matlabcontrol.MatlabProxy.MatlabThreadCallable;
import matlabcontrol.MatlabProxy.MatlabThreadProxy;
import com.mathworks.jmi.Matlab;
import com.mathworks.jmi.NativeMatlab;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

			@Override
			public Void call(MatlabThreadProxy proxy) throws MatlabInvocationException {
				proxy.eval(command);

				return null;
			}
		});
	}

	static Object[] returningEval(final String command, final int nargout) throws MatlabInvocationException {
		return invokeAndWait(new MatlabThreadCallable<Object[]>() {
			@Override
			public Object[] call(MatlabThreadProxy proxy) throws MatlabInvocationException {
				return proxy.returningEval(command, nargout);
			}
		});
	}

	static void feval(final String functionName, final Object... args) throws MatlabInvocationException {
		invokeAndWait(new MatlabThreadCallable<Void>() {
			@Override
			public Void call(MatlabThreadProxy proxy) throws MatlabInvocationException {
				proxy.feval(functionName, args);

				return null;
			}
		});
	}

	static Object[] returningFeval(final String functionName, final int nargout, final Object... args)
			throws MatlabInvocationException {