многопоточная работа
Пытаюсь прикрутить многопочтоку в colorer в рамках far. И столкнулся с взаимной блокировкой, которую не понимаю как обойти.
мой код тут https://github.com/ctapmex/far2l/tree/thread . всё крутится вокруг https://github.com/ctapmex/far2l/blob/thread/colorer/src/pcolorer2/ColorerWorker.cpp . изменений на 3 коммита, можно глянуть. сама раскраска еще не работает, там отрабатывается логика передачи/получения данных между потоками на примитивах.
логика работы следующая
- при открытии редактора запускается отдельный поток из ColorerWorker
- потоку дается задание обработать строки
- поток обращается за строкой в буфер. если в буфере её нет, то вызывается Info.AdvControl(Info.ModuleNumber, ACTL_SYNCHRO, &cmd, nullptr); , который в последствии передает управление плагину в основном потоке Far. плагин получив команду делает push массива строк в сторону потока.
- когда поток обработал нужное число строк, отображаемое сейчас в редакторе, он через Info.AdvControl(Info.ModuleNumber, ACTL_SYNCHRO, &cmd, nullptr); посылает команду, что надо отрисовать.
и всё работает более или менее нормально. данные гуляют как надо. Но проблема возникает при закрытии редактора, когда ловим взаимную блокировку.
функция Info.AdvControl в отличии от far3 обернута в "многопоточку". Она не отработает пока не освободится мютекс основного потока. и мы получаем следующее
- основной поток фара работает, и вызывает colorer с командой закрытия редактора. мютекс фара заблокирован, обработка идет в плагине.
- в это время поток смотрит, что строки кончились и вызывает AdvControl, и встает на ожидание мютекса , заблокированного в пункте 1 . так же в функции получения этих строк взведен мютекс потока, чтобы никто не вклинился.
- в рамках обработки закрытия редактора colorer вызывает деструктор , в рамках которого пытается остановить поток предварительно захватив его мютекс.
- в итоге два потока ждут друг друга
пока не понимаю как победить. под far3 не пробовал еще, но если там нет мютексов на AdvControl, то проблемы быть не должно.
спасибо @shmuz , подсказал попробовать AdvControlAsync. пока полет нормальный. issue пока не закрываю, вдруг еще вопросы будут