void VRWindowManager::stopWindows() {
    cout << "VRWindowManager::stopWindows" << endl;
    BarrierRefPtr barrier = Barrier::get("PVR_rendering", true);
    while (barrier->getNumWaiting() < VRWindow::active_window_count) usleep(1);
    for (auto w : getWindows() ) w.second->stop();
    barrier->enter(VRWindow::active_window_count+1);
}
void VRWindowManager::updateWindows() {
    if (rendering_paused) return;
    auto scene = VRScene::getCurrent();
    if (scene) scene->allowScriptThreads();

    ract->setResetStatistics(false);
    StatCollector* sc = ract->getStatCollector();
    if (sc) {
        sc->reset();
        sc->getElem(VRGlobals::FRAME_RATE.statFPS)->add(VRGlobals::FRAME_RATE.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP1.statFPS)->add(VRGlobals::UPDATE_LOOP1.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP2.statFPS)->add(VRGlobals::UPDATE_LOOP2.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP3.statFPS)->add(VRGlobals::UPDATE_LOOP3.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP4.statFPS)->add(VRGlobals::UPDATE_LOOP4.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP5.statFPS)->add(VRGlobals::UPDATE_LOOP5.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP6.statFPS)->add(VRGlobals::UPDATE_LOOP6.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP7.statFPS)->add(VRGlobals::UPDATE_LOOP7.fps);
        sc->getElem(VRGlobals::RENDER_FRAME_RATE.statFPS)->add(VRGlobals::RENDER_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SLEEP_FRAME_RATE.statFPS)->add(VRGlobals::SLEEP_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SWAPB_FRAME_RATE.statFPS)->add(VRGlobals::SWAPB_FRAME_RATE.fps);
        sc->getElem(VRGlobals::WINDOWS_FRAME_RATE.statFPS)->add(VRGlobals::WINDOWS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SCRIPTS_FRAME_RATE.statFPS)->add(VRGlobals::SCRIPTS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::PHYSICS_FRAME_RATE.statFPS)->add(VRGlobals::PHYSICS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::GTK1_FRAME_RATE.statFPS)->add(VRGlobals::GTK1_FRAME_RATE.fps);
        sc->getElem(VRGlobals::GTK2_FRAME_RATE.statFPS)->add(VRGlobals::GTK2_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SMCALLBACKS_FRAME_RATE.statFPS)->add(VRGlobals::SMCALLBACKS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SETUP_FRAME_RATE.statFPS)->add(VRGlobals::SETUP_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SCRIPTS_FRAME_RATE.statFPS)->add(VRGlobals::SCRIPTS_FRAME_RATE.fps);
    }

    //TODO: use barrier->getnumwaiting to make a state machine, allways ensure all are waiting!!

    BarrierRefPtr barrier = Barrier::get("PVR_rendering", true);

    auto updateSceneLinks = [&]() {
        for (auto view : VRSetup::getCurrent()->getViews()) {
            if (auto r = view->getRenderingL()) r->updateSceneLink();
            if (auto r = view->getRenderingR()) r->updateSceneLink();
        }
    };

    auto wait = [&](int timeout = -1) {
        int pID = VRProfiler::get()->regStart("window manager barrier");

        if (timeout > 0) {
            size_t tEnter = time(0);
            while (barrier->getNumWaiting() < VRWindow::active_window_count) {
                usleep(1);
                size_t tNow = time(0);
                int delta = tNow - tEnter;
                if (delta >= timeout) {
                    cout << "WARNING! skipping barrier!" << endl;
                    return false;
                }
            }
        }

        barrier->enter(VRWindow::active_window_count+1);
        VRProfiler::get()->regStop(pID);
        return true;
    };

    //TODO:
    // [0423/180710:WARNING:message_in_transit_queue.cc(18)] Destroying nonempty message queue

    auto tryRender = [&]() {
        if (barrier->getNumWaiting() != VRWindow::active_window_count) return true;
        if (!wait()) return false;
        /** let the windows clear their change lists **/
        if (!wait()) return false;
        auto clist = Thread::getCurrentChangeList();
        auto Ncreated = clist->getNumCreated();
        VRGlobals::NCHANGED = clist->getNumChanged();
        VRGlobals::NCREATED = Ncreated;
        if (Ncreated > 50) doRenderSync = true; // to reduce memory issues with big scenes
        for (auto w : getWindows() ) if (auto win = dynamic_pointer_cast<VRMultiWindow>(w.second)) if (win->getState() == VRMultiWindow::INITIALIZING) win->initialize();
        commitChanges();
        if (!wait()) return false;
        /** let the windows merge the change lists **/
        if (!wait()) return false;
        //if (clist->getNumCreated() > 0) cout << "VRWindowManager::updateWindows " << clist->getNumCreated() << " " << clist->getNumChanged() << endl;
        for (auto w : getWindows() ) if (auto win = dynamic_pointer_cast<VRGtkWindow>(w.second)) win->render();
        clist->clear();
        if (doRenderSync) if (!wait(60)) return false;
        doRenderSync = false;
        return true;
        //sleep(1);
    };

    updateSceneLinks();

    if (!tryRender()) {
        cout << "WARNING! a remote window hangs or something!\n";
        for (auto w : getWindows() ) {
            auto win = dynamic_pointer_cast<VRMultiWindow>(w.second);
            if (!win) continue;
            if (win->isWaiting()) continue;
            cout << "WARNING!  window " << win->getName() << " is hanging, state: " << win->getStateString() << endl;
            WARN("WARNING! Lost connection with " + win->getName());
            win->reset();
        }
    }

    if (scene) scene->blockScriptThreads();
}