VSTGUI: Соглашения для editor::open и editor::close

При написании нового vst-плагина с использованием VSTGUI я действительно борюсь с тем, как использовать библиотеку, и основной прогресс достигается за счет догадок и отладки после (потому что на самом деле нет никакой документации, кроме миллиона строк и ygrabit, в котором говорится чуть больше, чем очевидное).

Пока все идет хорошо, но мой последний вклад в проект касался потоков, которые сделали дизайн немного более проблематичным. В частности, я работаю над набором текстовых меток в контейнере (выполняя неатомарные операции), и они могут (и, очевидно, разрушаются) без моего ведома, когда пользователь закрывает окно. Даже добавление проверок непосредственно перед изменением элементов может быть проблемой. Поэтому мне действительно нужно контролировать время жизни этих объектов (что нормально), за исключением случаев, когда они отображаются в CViewContainer, он автоматически принимает на себя право собственности.

Я понятия не имею, как написать основу редактора, поэтому я использовал для этого программу под названием VSTGUIBuilder и добавил (и, по сути, переписал) то, что мне было нужно. Однако, поскольку все «представления», с которыми вы можете работать, требуют либо родителя, либо системного окна, вы не можете создавать экземпляры каких-либо представлений/элементов управления до достижения функции AEffEditor::Open(), которая вызывается всякий раз, когда открывается ваше окно. А метод AEffEditor::close() вызывается всякий раз, когда окно закрывается. Теперь vstguibuilder поставил

delete frame;

внутри метода AEffEditor::close(), который предлагает вам перестраивать и распределять все ресурсы при каждом открытии и закрытии. Может ли это быть правдой? И если это так, могу ли я защитить содержимое моего контейнера (который для деталей является вектором‹ CTextLabel *>) от удаления в середине функции? После этого избавиться от него не проблема, я просто беспокоюсь о сегфоултах при его изменении.

Использование мьютексов и тому подобного действительно является последним средством (если вызов исходит от хоста), я ни в коем случае не хочу вешать хост, если мой код дает сбой и никогда не освобождается.

Редактировать: я нашел решение, которое не так элегантно, но работает безопасно. Вот код рабочей функции:

        while(bLock) {
            Sleep(0);
        }
        bLock = true;

        if(msgs.empty())
            return;

        /*
            Prevent someone deletes our lines in close().
            we create a copy of the container to be 100% sure
            and increase the reference count, so we can safely
            work with our own container and we 'forget' them
            afterwards, so they will be deleted if needed.
            This ensures that close AND open can be called 
            meanwhile we are working with the lines
        */
        bDeleteLock = true;
        // also the copy constructor should work as expected here
        // since we are working with pointers, we still reference the same content.
        auto copy_lines = lines;

        for each(auto line in copy_lines) {
            line->remember();
        }
        bDeleteLock = false;

        ...

        for each(auto line in copy_lines) {
            line->forget();
        }
        cont->setDirty();

bLock — это еще один «мьютекс», защищающий очередь сообщений, которую эта функция распечатает. bDeleteLock защищает процесс копирования строкового контейнера и «запоминания» их, а затем мгновенно освобождает. Оба объявлены как volatile bool, разве этого не должно быть достаточно? Вот метод close() между прочим.

    void CConsole::Close() {
        // locking lines while copying them over in a container we can work with
        while(bDeleteLock)
            Sleep(0);
        //waiting for bLock is not needed because it wont get deleted.
        if(!visible) //if we are not visible it's our responsibility to remove the view
            delete cont;

        lines.clear();

    }

person Shaggi    schedule 28.05.2013    source источник


Ответы (1)


Ах, VSTGUI, это навевает некоторые мрачные воспоминания. ;) А если серьезно, то да, вероятно, вам придется использовать мьютекс, чтобы предотвратить зависание хоста. Необходимость создавать все экземпляры при повторном открытии окна кажется глупой, но вы можете видеть, что многие плагины делают именно это.

Одним из возможных обходных путей является использование сегмента общей памяти для кешированных данных просмотра, а затем передача ссылки на местоположение обратно в ваш плагин.

person Nik Reiman    schedule 29.05.2013
comment
Да.. Готов поспорить. Да, в итоге я заблокировал данные в базовом мьютексе, вы можете увидеть опубликованное решение. Я действительно нахожу создание экземпляра странным, но я думаю, что это способ сэкономить память, пока окно не открыто (за счет вычислительной мощности при его открытии). - person Shaggi; 29.05.2013