// 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;
	@SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "False positive.")
	static void exit() {
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				try {
					Matlab.mtFevalConsoleOutput("exit", null, 0);
				}
				//This should never fail, and if it does there is no way to consistently report it back to the caller
				//because this method does not block
				catch (Exception e) {
					// make as much noise as we can
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
		};

		if (NativeMatlab.nativeIsMatlabThread()) {
			runnable.run();
		} else {
			Matlab.whenMatlabIdle(runnable);
		}
	}

	//The following functions wait for MATLAB to complete the computation before returning
	//See MatlabProxy for the method documentation, acts as if running inside MATLAB
	//(A LocalMatlabProxy is just a thin wrapper around these methods)

	static void setVariable(final String variableName, final Object value) throws MatlabInvocationException {
// 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;

	@SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "False positive.")
	static void exit() {
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				try {
					Matlab.mtFevalConsoleOutput("exit", null, 0);
				}
				//This should never fail, and if it does there is no way to consistently report it back to the caller
				//because this method does not block
				catch (Exception e) {
					// make as much noise as we can
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
		};

		if (NativeMatlab.nativeIsMatlabThread()) {
			runnable.run();
		} else {
			Matlab.whenMatlabIdle(runnable);
		}
	}

	//The following functions wait for MATLAB to complete the computation before returning
	//See MatlabProxy for the method documentation, acts as if running inside MATLAB
	//(A LocalMatlabProxy is just a thin wrapper around these methods)

	static void setVariable(final String variableName, final Object value) throws MatlabInvocationException {
		invokeAndWait(new MatlabThreadCallable<Void>() {