class SeparateTextGUIThread extends AbstractTextGUIThread implements AsynchronousTextGUIThread {
    private volatile State state;
    private final Thread textGUIThread;
    private final CountDownLatch waitLatch;

    private SeparateTextGUIThread(TextGUI textGUI) {
        super(textGUI);
        this.waitLatch = new CountDownLatch(1);
        this.textGUIThread = new Thread("LanternaGUI") {
            @Override
            public void run() {
                mainGUILoop();
            }
        };
        state = State.CREATED;
    }

    @Override
    public void start() {
        textGUIThread.start();
        state = State.STARTED;
    }

    @Override
    public void stop() {
        if(state != State.STARTED) {
            return;
        }

        state = State.STOPPING;
    }

    @Override
    public void waitForStop() throws InterruptedException {
        waitLatch.await();
    }

    @Override
    public void waitForStop(long time, TimeUnit unit) throws InterruptedException {
        waitLatch.await(time, unit);
    }

    @Override
    public State getState() {
        return state;
    }

    @Override
    public Thread getThread() {
        return textGUIThread;
    }

    @Override
    public void invokeLater(Runnable runnable) throws IllegalStateException {
        if(state != State.STARTED) {
            throw new IllegalStateException("Cannot schedule " + runnable + " for execution on the TextGUIThread " +
                    "because the thread is in " + state + " state");
        }
        super.invokeLater(runnable);
    }

    private void mainGUILoop() {<FILL_FUNCTION_BODY>}


    /**
     * Factory class for creating SeparateTextGUIThread objects
     */
    public static class Factory implements TextGUIThreadFactory {
        @Override
        public TextGUIThread createTextGUIThread(TextGUI textGUI) {
            return new SeparateTextGUIThread(textGUI);
        }
    }
}

        try {
            //Draw initial screen, after this only draw when the GUI is marked as invalid
            try {
                textGUI.updateScreen();
            }
            catch(IOException e) {
                exceptionHandler.onIOException(e);
            }
            catch(RuntimeException e) {
                exceptionHandler.onRuntimeException(e);
            }
            while(state == State.STARTED) {
                try {
                    if (!processEventsAndUpdate()) {
                        try {
                            Thread.sleep(1);
                        }
                        catch(InterruptedException ignored) {}
                    }
                }
                catch(EOFException e) {
                    stop();
                    if (textGUI instanceof WindowBasedTextGUI) {
                        // Close all windows on EOF
                        for (Window window: ((WindowBasedTextGUI) textGUI).getWindows()) {
                            window.close();
                        }
                    }
                    break; //Break out quickly from the main loop
                }
                catch(IOException e) {
                    if(exceptionHandler.onIOException(e)) {
                        stop();
                        break;
                    }
                }
                catch(RuntimeException e) {
                    if(exceptionHandler.onRuntimeException(e)) {
                        stop();
                        break;
                    }
                }
            }
        }
        finally {
            state = State.STOPPED;
            waitLatch.countDown();
        }
    
<methods>public void <init>(com.googlecode.lanterna.gui2.TextGUI) ,public void invokeAndWait(java.lang.Runnable) throws java.lang.IllegalStateException, java.lang.InterruptedException,public void invokeLater(java.lang.Runnable) throws java.lang.IllegalStateException,public synchronized boolean processEventsAndUpdate() throws java.io.IOException,public void setExceptionHandler(com.googlecode.lanterna.gui2.TextGUIThread.ExceptionHandler) <variables>protected final non-sealed Queue<java.lang.Runnable> customTasks,protected com.googlecode.lanterna.gui2.TextGUIThread.ExceptionHandler exceptionHandler,protected final non-sealed com.googlecode.lanterna.gui2.TextGUI textGUI