Я пишу графическую программу для Linux, в C, используя Xlib. Проблема проста. У меня есть событие, которое происходит вне Xlib-события l oop, которое должно быть обработано и приведет к некоторому изменению того, что отображается на экране. В моем случае я пытаюсь заставить курсор мигать внутри текстового поля. Мое событие l oop выглядит так:
XEvent event;
while(window.loop_running == 1) {
XNextEvent(window.dis, &event);
event_handler(&window, &event); // This is a custom function to handle events
}
Решение 1a:
Моей первой мыслью было создание второго l oop с pthreads. Этот второй l oop может обрабатывать асинхронное событие и рисовать по мере необходимости на экране. Тем не менее, Xlib не подходит для нескольких потоков. Даже если бы я использовал мьютекс для блокировки функции event_handler (), во время асинхронного рисования во втором l oop у меня все еще периодически возникали сбои из X. Кроме того, если событие l oop не циклично, после примерно 10 вызовов из pthread l oop программа блокируется.
Решение 1b:
Эту проблему можно решить, вызвав XInitThreads () в начале моей программы. Однако это заставляет valgrind сообщать об утечке памяти. Кажется, что выделена некоторая память, которая не освобождается при выходе. И вызовы XCloseDisplay () просто зависают, если я вызываю XInitThreads (). Я до сих пор не понял, как уничтожить и очистить windows в моей программе, но это может быть лучше сохранить для отдельного вопроса. Кроме того, вызов XInitThreads () при запуске моей программы останавливает зависание программы после 10 вызовов из pthread l oop без циклического повторения события l oop. Однако вызовы к X начинают блокироваться примерно после 10 вызовов из строки l oop. Вещи на короткое время возобновляются после циклического события l oop, например, при наведении курсора на окно Однако вызовы быстро начинают блокироваться снова, когда активность события in-l oop прекращается. Интересно, что я заметил, что могу повторить эту проблему в некоторых других программах, таких как Bluefi sh. Если я открою Bluefi sh, запустите курсор в главном текстовом поле, а затем переведите курсор мыши, через 10 секунд курсор перестанет мигать. Ясно, что это не всегда проблема, поскольку такие вещи, как дисплей видеопроигрывателя, зависли бы после некоторого периода, когда не было запущено ни одного события X.
Решение 1 c:
Я могу остановить зависание окна, используя XSendEvent () для циклического повторения события l oop после завершения рисования из pthread l oop. Тем не менее, это кажется действительно хаки. И я не могу гарантировать, что это сработает, поскольку я не знаю точно, в какой момент Х прекратит слушать. Я не смог определить причину этой проблемы root. Как я уже сказал, это происходит примерно через 10 секунд, но это зависит от того, как я изменяю частоту циклов мигающего курсора. Я испытываю желание предположить, что это - функция фактических вызовов к X, сделанным. Есть примерно 2 на пиксель, на перерисовку. Он должен: 1) установить цвет переднего плана и 2) нарисовать пиксель из буфера растрового изображения на экране. В настоящее время мое окно поддерживает только разрешение 640x480. Конечно, я просто предполагаю, что это можно использовать для определения точки сбоя, поскольку я действительно не знаю причину.
Решение 2:
Я могу отбросьте все это и повторно реализуйте событие l oop, опрашивая очередь событий с помощью XEventsQueued (), обрабатывая их по мере их поступления. Но я буду честен, я ненавижу это решение. Это действительно хакерское решение, которое увеличит вычислительную мощность, необходимую для этого приложения, и увеличит задержку ответа на событие, так как я хотел бы перевести поток между опросами, чтобы предотвратить просто вращение потока и привязку ядра процессора. Я пишу эту программу с целью быстрой, стабильной и экономичной программы.
У кого-нибудь есть решение? Это такая простая и фундаментальная проблема, но я видел только примеры приложений, которые используют XNextEvent в событии l oop. Я не нашел примеров того, как обрабатывать события l oop. Спасибо за помощь. Я новый участник Stack Overflow. Это мой первый пост. Поэтому я прошу прощения, если я совершил ошибку.