Тестирование разных контейнеров и другая болтовня
|
|
laser | Дата: Воскресенье, 27.03.2022, 19:03 | Сообщение # 31 |
Лейтенант
Группа: Пользователи
Сообщений: 57
Статус: Offline
| Цитата haav ( ) но вроде эти штуки:gdk_threads_enter , gdk_threads_leave
как раз и нужны для синхронизации. Если синхронизировать, то везде. В основном потоке этих штук не наблюдаю и ничего не мешает жмякнуть на Textgadget и получить бяку.
Цитата haav ( ) Наверное именно для PostEvent (а может и не только для нее) все таки синхронизация внутренне выполняется. В винде PostEvent это PostMessage. В других хз. Функция добавляет сообщение в очередь окна и оно доставляется обработчику который может быть в другом потоке.
|
|
| |
haav | Дата: Воскресенье, 27.03.2022, 19:55 | Сообщение # 32 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Цитата laser ( ) Если синхронизировать, то везде. В основном потоке этих штук не наблюдаю и ничего не мешает жмякнуть на Textgadget и получить бяку.
В основном коде тоже есть , просто ты это не заметил. Да такой способ кажется не совсем логичным , но во многих примерах в сети указывается именно такой способ. Поэтому я и сказал , что не уверен на 100%. Но сколько я не пытался поймать багу , просматривал вывод в консоли и пока все работало корректно. Судя по всему в критическую секцию попадает весь код основного потока и это дает гарантию , что в одно время доступ может быть только у одного потока. Чтобы понять так это или нет , нужно искать авторитетные источники , но где бы их найти...
Цитата laser ( ) В винде PostEvent это PostMessage. В других хз. Функция добавляет сообщение в очередь окна и оно доставляется обработчику который может быть в другом потоке.
Я посмотрел в отладчике процедуру PostEvent , похоже действительно внутренне синхронизация присутствует , о чем как бы намекает используемая функция pthread_mutex_unlock:
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
laser | Дата: Воскресенье, 27.03.2022, 20:56 | Сообщение # 33 |
Лейтенант
Группа: Пользователи
Сообщений: 57
Статус: Offline
| Цитата haav ( ) В основном коде тоже есть , просто ты это не заметил. Может и не заметил. Покажи где синхронизируется доступ к общей глобальной переменной sValue? Что мешает одновременно записать в нее строку с основном и созданном потоке? Представь что основной поток освободил буфер строки и начал запись, а в это время поток тоже освобождает буфер и... Думаю понимаешь к чему приведет.
Цитата haav ( ) Я посмотрел в отладчике процедуру PostEvent , похоже действительно внутренне синхронизация присутствует , о чем как бы намекает используемая функция pthread_mutex_unlock: Из кода совершенно непонятно что синхронизировал мьютекс. Может доступ к внутреннему списку окон или еще к чему-то.
|
|
| |
haav | Дата: Воскресенье, 27.03.2022, 22:18 | Сообщение # 34 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Цитата laser ( ) Может и не заметил. Покажи где синхронизируется доступ к общей глобальной переменной sValue? Что мешает одновременно записать в нее строку с основном и созданном потоке? Представь что основной поток освободил буфер строки и начал запись, а в это время поток тоже освобождает буфер и... Думаю понимаешь к чему приведет.
С мьютексами , что идут в FB как раз такая логика , о которой ты говоришь. Но в данном случае я не знаю , как правильно. Возможно ты прав. И поверь я ведь не спорю и в твоих словах звучит здравая логика. Я лишь говорю , что не знаю , и что примеры , попадавшиеся мне в сети были именно так устроены (возможно их авторы накосячили и ввели меня в заблуждение).
Цитата laser ( ) Из кода совершенно непонятно что синхронизировал мьютекс. Может доступ к внутреннему списку окон или еще к чему-то.
Я просто залез во внутренности PostEvent. Конечно я не изучал что там и откуда растет. Но все таки логично предположить , что раз PostEvent вызывается из отдельного потока , то синхронизация требуется. Ведь по сути PostEvent на линуксе внутренее является просто запуском таймера с колбак процедурой (одноразовый вызов колбак).
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
haav | Дата: Понедельник, 28.03.2022, 07:45 | Сообщение # 35 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Ну вот , накаркал laser Получил я все таки проблему с этим кодом. И дело даже не в переменной , я ее вообще убрал из кода. Когда поменял WaitEvent на (WindowEvent +sleep 40) , а в потоке сделал статично sleep 20 вместо Sleep(Rnd*1000) , вылезло это:
Цитата [xcb] Unknown sequence number while processing reply [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called [xcb] Aborting, sorry about that. FBTEMP: ../../src/xcb_io.c:639: _XReply: Проверочное утверждение «!xcb_xlib_threads_sequence_lost» не выполнено.
Aborting due to runtime error 14 ("abnormal termination" signal) in FBTEMP.bas::THSUB()
Причем как я только не пытался играться с gdk_threads_enter , gdk_threads_leave в основном потоке , все равно проблемы (либо программа висит , либо вылезает ошибка).
Нет , все таки GTK не буду использовать для многопотока. Самый проверенный метод: GUI отдельно , логика отдельно. Логику можно в многопоток. На винде кстати тоже лучше придерживаться этого принципа. Меньше головной боли.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
bxusinboy | Дата: Понедельник, 28.03.2022, 16:03 | Сообщение # 36 |
Рядовой
Группа: Пользователи
Сообщений: 16
Статус: Offline
| Цитата haav ( ) Причем как я только не пытался играться с gdk_threads_enter , gdk_threads_leave в основном потоке , все равно проблемы (либо программа висит , либо вылезает ошибка). Можете дать пример с работой с потоками, который не работает. gdk_threads_enter , gdk_threads_leave невозможно использовать в основном потоке (тогда программа будет висеть, ничего не делая).
|
|
| |
haav | Дата: Понедельник, 28.03.2022, 17:01 | Сообщение # 37 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Цитата bxusinboy ( ) Можете дать пример с работой с потоками, который не работает. gdk_threads_enter , gdk_threads_leave невозможно использовать в основном потоке (тогда программа будет висеть, ничего не делая).
Пример то не проблема , но в примере используется библиотека , поэтому разобраться будет непросто.
Вот этот пример работает кажется без проблем (по крайней мере у меня не было проблем): http://freebasic.ucoz.com/forum/4-529-2771-16-1648355515 (2 пример в сообщении)
А вот если его немного переписать , то уже проблемы:
Код #include "gtk/gtk.bi" #inclib "gthread-2.0" g_thread_init(0) gdk_threads_init() #include "window9.bi"
Declare Function thSub Cdecl(p As Integer) As Any Ptr
gdk_threads_enter()
Dim As Integer Event Dim As GError Ptr pErr
Dim Shared As String sValue
Openwindow("",10,10,100,100) Textgadget(1,10,40,100,20,"textgadget")
If g_thread_create(Cast(Any Ptr ,@thSub()), Cast(Any Ptr ,1), False, @pErr) = 0 Then Print "Failed to create thread 1", pErr->message End Endif
If g_thread_create(Cast(Any Ptr ,@thSub()), Cast(Any Ptr ,2), False, @pErr) = 0 Then Print "Failed to create thread 2", pErr->message End Endif
Do Event=Windowevent() If Event= Eventclose Then End If Event=Eventgadget Then Select Case Eventnumber Case 1 sValue = "main thread" Setgadgettext(1,sValue) End Select Endif sleep(40) Loop
gdk_threads_leave()
End
Function thSub Cdecl(p As Integer) As Any Ptr Do Sleep(20) gdk_threads_enter() If p = 1 Then Setgadgettext(1 , "thread 1") Else Setgadgettext(1 , "thread 2") Endif gdk_flush() gdk_threads_leave() Loop Return 0 End Function
Но тут как повезет , иногда он может даже работать. Хотя у меня в большинстве случаев либо виснет , либо вываливает ошибку.
Ты если хорошо понимаешь в этом , лучше научи меня на примере с чистым GTK. А я уж потом как-нибудь его скрещу с библиотекой
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
bxusinboy | Дата: Понедельник, 28.03.2022, 17:57 | Сообщение # 38 |
Рядовой
Группа: Пользователи
Сообщений: 16
Статус: Offline
| Код #include "gtk/gtk.bi" #inclib "gthread-2.0" g_thread_init(0) gdk_threads_init() #include "window9.bi"
Declare Function thSub Cdecl(p As Integer) As Any Ptr
[b]gdk_threads_enter()[/b]
Dim As Integer Event Dim As GError Ptr pErr
Dim Shared As String sValue
Openwindow("",10,10,100,100) Textgadget(1,10,40,100,20,"textgadget")
If g_thread_create(Cast(Any Ptr ,@thSub()), Cast(Any Ptr ,1), False, @pErr) = 0 Then Print "Failed to create thread 1", pErr->message End Endif
If g_thread_create(Cast(Any Ptr ,@thSub()), Cast(Any Ptr ,2), False, @pErr) = 0 Then Print "Failed to create thread 2", pErr->message End Endif
Do Event=Windowevent() If Event= Eventclose Then End If Event=Eventgadget Then Select Case Eventnumber Case 1 sValue = "main thread" Setgadgettext(1,sValue) End Select Endif sleep(40) Loop
[b]gdk_threads_leave()[/b]
End
Function thSub Cdecl(p As Integer) As Any Ptr Do Sleep(20) gdk_threads_enter() If p = 1 Then Setgadgettext(1 , "thread 1") Else Setgadgettext(1 , "thread 2") Endif gdk_flush() gdk_threads_leave() Loop Return 0 End Function
В коде выделенные жирным строки надо удалить. У меня работал без проблем (если не удалить тоже). Но если я удаляю gdk_threads_enter() и gdk_threads_leave() из функции thSub тогда программа виснет. В другом случае я не увидел сбой программы.
|
|
| |
haav | Дата: Понедельник, 28.03.2022, 18:35 | Сообщение # 39 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| У меня все равно сбои , даже если удалить эти функции. Однако , если из кода убрать gdk_flush , то все начинает работать хорошо (это я уже экспериментировать начал ). Ее почему-то во многих примерах рекомендовалось использовать в процедуре дополнительного потока. А у меня наоборот без нее все хорошо. bxusinboy! Проверь пожалуйста , будет ли работать без gdk_flush и если работает , то стабильно ли. Желательно сделать несколько запусков программы. И кстати , а где написано что функции gdk_threads_enter() , gdk_threads_leave() нельзя использовать в основном потоке?
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
bxusinboy | Дата: Вторник, 29.03.2022, 04:36 | Сообщение # 40 |
Рядовой
Группа: Пользователи
Сообщений: 16
Статус: Offline
| Цитата haav ( ) bxusinboy! Проверь пожалуйста , будет ли работать без gdk_flush и если работает , то стабильно ли. Желательно сделать несколько запусков программы. Да, без gdk_flush тоже работает. Запускал программу много раз.
Цитата haav ( ) И кстати , а где написано что функции gdk_threads_enter() , gdk_threads_leave() нельзя использовать в основном потоке? В основном потоке в сети увидел только такой код:
Код gdk_threads_enter() gtk_main() gdk_threads_leave()
Цитата Эта функция знаменует собой начало критического раздела, в котором функции GDK и GTK+ могут быть вызваны безопасно и без возникновения условий гонки. Только одна нить за раз может быть в таком критическом разделе.
http://www.manpagez.com/html....s-enter
Условия гонки это когда несколько потоков одновременно собирается изменить данные одного gtk widget'а, я так думаю.
Оказывается ещё gdk_threads_enter и gdk_threads_leave устарел с версии 3.6.
|
|
| |
haav | Дата: Вторник, 29.03.2022, 06:50 | Сообщение # 41 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Цитата bxusinboy ( ) Да, без gdk_flush тоже работает. Запускал программу много раз.
Благодарю за тест.
Цитата bxusinboy ( ) Оказывается ещё gdk_threads_enter и gdk_threads_leave устарел с версии 3.6.
Да у них много функций утыкано такими надписями. Бывает на одной версии (с разными подверсиями) функцию сначала переименовывают , а в следующей подверсии вообще удаляют. Я не шибко обращаю внимание на эти предупреждения. Просто проверяю: работает ли на самой последней версии или нет. В данном случае на самой последней версии 3.22 все работает , а дальше развивать GTK2 и GTK3 уже не будут. GTK4 мне вообще не интересна , и я не думаю , что когда-нибудь буду писать что-то с GTK4.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
WQ | Дата: Пятница, 08.04.2022, 14:29 | Сообщение # 42 |
Полковник
Группа: Проверенные
Сообщений: 215
Статус: Offline
| Цитата haav ( ) Я даже не думал , что это может быть нужно. Но вообще это не проблема , ты всегда можешь добавить процедуру перечисления. Вот пример: Периодически возникает такая потребность, в хэш-таблице IUP для этого есть специальные функции
Для завершения жизни таблицы нужно вызывать
Код pTable->cleartable() pTable->freetable()
Возможно, лучше, если pTable->freetable() будет сразу включать pTable->cleartable() ? Или добавить специальную функцию для замены этих двух?
Использовал в одной программе десяток хэш-таблиц из Containers, вроде все нормально То, что можно использовать произвольный тип данных - очень удобно
|
|
| |
haav | Дата: Пятница, 08.04.2022, 16:18 | Сообщение # 43 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Цитата WQ ( ) Периодически возникает такая потребность, в хэш-таблице IUP для этого есть специальные функции
Понимаешь в чем дело. Придется делать что-то типа колбака , а это лишнее время на вызовы. Я же показал , как это можно делать напрямую. Неужели сложно?
Цитата WQ ( ) Возможно, лучше, если pTable->freetable() будет сразу включать pTable->cleartable() ? Или добавить специальную функцию для замены этих двух?
Извини , но я не буду делать дополнительную функцию , которую ты можешь написать за 10-15 секунд. И потом это 2 функции разного назначения. 1) cleartable очищает таблицу с возможностью дальнейшего использования. 2) freetable используется уже для удаления таблицы , после очистки. Дальнейшие действия с таблицей уже невозможны (только создавать новую).
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
laser | Дата: Пятница, 08.04.2022, 16:37 | Сообщение # 44 |
Лейтенант
Группа: Пользователи
Сообщений: 57
Статус: Offline
| Цитата haav ( ) 2) freetable используется уже для удаления таблицы , после очистки. Дальнейшие действия с таблицей уже невозможны (только создавать новую). Из freetable нужно вызывать cleartable и тогда в коде достаточно будет тока freetable которая также осовбодит память. В FB есть классы. Оформи таблицу как класс и чисти в деструкторе. Это даже лучше потому что автоматом освободит память при уничтожении экземпляра.
|
|
| |
haav | Дата: Пятница, 08.04.2022, 19:10 | Сообщение # 45 |
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Статус: Offline
| Цитата laser ( ) Из freetable нужно вызывать cleartable и тогда в коде достаточно будет тока freetable которая также осовбодит память. В FB есть классы. Оформи таблицу как класс и чисти в деструкторе. Это даже лучше потому что автоматом освободит память при уничтожении экземпляра.
Не надо там ничего изобретать.
@WQ
Если для тебя так важно , чтобы очистка происходила одной функцией , просто помести cleartable в функцию freetable. Это как-то так должно быть:
Код Sub THASHTABLE##_mk_##_mv_.freetable() cleartable() Deallocate(pArray) End Sub
Ведь контейнеры - это не скомпилированная библиотека , ты в любой момент можешь вносить любые изменения.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
|