FreeBasic
Главная
Вход
Регистрация
Четверг, 05.12.2024, 19:07Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 3 из 4
  • «
  • 1
  • 2
  • 3
  • 4
  • »
Тестирование разных контейнеров и другая болтовня
laserДата: Воскресенье, 27.03.2022, 19:03 | Сообщение # 31
Лейтенант
Группа: Пользователи
Сообщений: 57
Репутация: -46
Статус: Offline
Цитата haav ()
но вроде эти штуки:gdk_threads_enter , gdk_threads_leave

как раз и нужны для синхронизации.
Если синхронизировать, то везде. В основном потоке этих штук не наблюдаю и ничего не мешает жмякнуть на Textgadget и получить бяку.

Цитата haav ()
Наверное именно для PostEvent (а может и не только для нее) все таки синхронизация внутренне выполняется.
В винде PostEvent это PostMessage. В других хз. Функция добавляет сообщение в очередь окна и оно доставляется обработчику который может быть в другом потоке.
 
haavДата: Воскресенье, 27.03.2022, 19:55 | Сообщение # 32
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Репутация: 50
Статус: Offline
Цитата laser ()
Если синхронизировать, то везде. В основном потоке этих штук не наблюдаю и ничего не мешает жмякнуть на Textgadget и получить бяку.


В основном коде тоже есть , просто ты это не заметил. Да такой способ кажется не совсем логичным , но во многих примерах в сети указывается именно такой способ. Поэтому я и сказал , что не уверен на 100%. Но сколько я не пытался поймать багу , просматривал вывод в консоли и пока все работало корректно. Судя по всему в критическую секцию попадает весь код основного потока и это дает гарантию , что в одно время доступ может быть только у одного потока. Чтобы понять так это или нет , нужно искать авторитетные источники , но где бы их найти...

Цитата laser ()
В винде PostEvent это PostMessage. В других хз. Функция добавляет сообщение в очередь окна и оно доставляется обработчику который может быть в другом потоке.


Я посмотрел в отладчике процедуру PostEvent , похоже действительно внутренне синхронизация присутствует , о чем как бы намекает используемая функция pthread_mutex_unlock:

Прикрепления: 3398220.png (41.5 Kb)


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
laserДата: Воскресенье, 27.03.2022, 20:56 | Сообщение # 33
Лейтенант
Группа: Пользователи
Сообщений: 57
Репутация: -46
Статус: Offline
Цитата haav ()
В основном коде тоже есть , просто ты это не заметил.
Может и не заметил. Покажи где синхронизируется доступ к общей глобальной переменной sValue?
Что мешает одновременно записать в нее строку с основном и созданном потоке?
Представь что основной поток освободил буфер строки и начал запись, а в это время поток тоже освобождает буфер и... Думаю понимаешь к чему приведет.

Цитата haav ()
Я посмотрел в отладчике процедуру PostEvent , похоже действительно внутренне синхронизация присутствует , о чем как бы намекает используемая функция pthread_mutex_unlock:
Из кода совершенно непонятно что синхронизировал мьютекс. Может доступ к внутреннему списку окон или еще к чему-то.
 
haavДата: Воскресенье, 27.03.2022, 22:18 | Сообщение # 34
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Репутация: 50
Статус: Offline
Цитата laser ()
Может и не заметил. Покажи где синхронизируется доступ к общей глобальной переменной sValue?
Что мешает одновременно записать в нее строку с основном и созданном потоке?
Представь что основной поток освободил буфер строки и начал запись, а в это время поток тоже освобождает буфер и... Думаю понимаешь к чему приведет.


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

Цитата laser ()
Из кода совершенно непонятно что синхронизировал мьютекс. Может доступ к внутреннему списку окон или еще к чему-то.


Я просто залез во внутренности PostEvent. Конечно я не изучал что там и откуда растет. Но все таки логично предположить , что раз PostEvent вызывается из отдельного потока , то синхронизация требуется. Ведь по сути PostEvent на линуксе внутренее является просто запуском таймера с колбак процедурой (одноразовый вызов колбак).



Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
haavДата: Понедельник, 28.03.2022, 07:45 | Сообщение # 35
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Репутация: 50
Статус: Offline
Ну вот , накаркал laser smile Получил я все таки проблему с этим кодом. И дело даже не в переменной , я ее вообще убрал из кода. Когда поменял 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
Репутация: 2
Статус: Offline
Цитата haav ()
Причем как я только не пытался играться с gdk_threads_enter , gdk_threads_leave в основном потоке , все равно проблемы (либо программа висит , либо вылезает ошибка).

Можете дать пример с работой с потоками, который не работает. gdk_threads_enter , gdk_threads_leave невозможно использовать в основном потоке (тогда программа будет висеть, ничего не делая).
 
haavДата: Понедельник, 28.03.2022, 17:01 | Сообщение # 37
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Репутация: 50
Статус: 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. А я уж потом как-нибудь его скрещу с библиотекой smile


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
bxusinboyДата: Понедельник, 28.03.2022, 17:57 | Сообщение # 38
Рядовой
Группа: Пользователи
Сообщений: 16
Репутация: 2
Статус: 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
Репутация: 50
Статус: Offline
У меня все равно сбои , даже если удалить эти функции. Однако , если из кода убрать gdk_flush , то все начинает работать хорошо (это я уже экспериментировать начал smile ). Ее почему-то во многих примерах рекомендовалось использовать в процедуре дополнительного потока. А у меня наоборот без нее все хорошо.
bxusinboy! Проверь пожалуйста , будет ли работать без gdk_flush и если работает , то стабильно ли. Желательно сделать несколько запусков программы. И кстати , а где написано что функции gdk_threads_enter() , gdk_threads_leave() нельзя использовать в основном потоке?


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
bxusinboyДата: Вторник, 29.03.2022, 04:36 | Сообщение # 40
Рядовой
Группа: Пользователи
Сообщений: 16
Репутация: 2
Статус: 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
Репутация: 50
Статус: 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
Репутация: 7
Статус: Offline
Цитата haav ()
Я даже не думал , что это может быть нужно. Но вообще это не проблема , ты всегда можешь добавить процедуру перечисления. Вот пример:
Периодически возникает такая потребность, в хэш-таблице IUP для этого есть специальные функции

Для завершения жизни таблицы нужно вызывать
Код
pTable->cleartable()
pTable->freetable()
Возможно, лучше, если pTable->freetable() будет сразу включать pTable->cleartable() ?
Или добавить специальную функцию для замены этих двух?

Использовал в одной программе десяток хэш-таблиц из Containers, вроде все нормально
То, что можно использовать произвольный тип данных - очень удобно
 
haavДата: Пятница, 08.04.2022, 16:18 | Сообщение # 43
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Репутация: 50
Статус: Offline
Цитата WQ ()
Периодически возникает такая потребность, в хэш-таблице IUP для этого есть специальные функции


Понимаешь в чем дело. Придется делать что-то типа колбака , а это лишнее время на вызовы. Я же показал , как это можно делать напрямую. Неужели сложно?

Цитата WQ ()
Возможно, лучше, если pTable->freetable() будет сразу включать pTable->cleartable() ?
Или добавить специальную функцию для замены этих двух?


Извини , но я не буду делать дополнительную функцию , которую ты можешь написать за 10-15 секунд. И потом это 2 функции разного назначения.
1) cleartable очищает таблицу с возможностью дальнейшего использования.
2) freetable используется уже для удаления таблицы , после очистки. Дальнейшие действия с таблицей уже невозможны (только создавать новую).


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
laserДата: Пятница, 08.04.2022, 16:37 | Сообщение # 44
Лейтенант
Группа: Пользователи
Сообщений: 57
Репутация: -46
Статус: Offline
Цитата haav ()
2) freetable используется уже для удаления таблицы , после очистки. Дальнейшие действия с таблицей уже невозможны (только создавать новую).
Из freetable нужно вызывать cleartable и тогда в коде достаточно будет тока freetable которая также осовбодит память.
В FB есть классы. Оформи таблицу как класс и чисти в деструкторе. Это даже лучше потому что автоматом освободит память при уничтожении экземпляра.
 
haavДата: Пятница, 08.04.2022, 19:10 | Сообщение # 45
Генералиссимус
Группа: Администраторы
Сообщений: 1373
Репутация: 50
Статус: Offline
Цитата laser ()
Из freetable нужно вызывать cleartable и тогда в коде достаточно будет тока freetable которая также осовбодит память.
В FB есть классы. Оформи таблицу как класс и чисти в деструкторе. Это даже лучше потому что автоматом освободит память при уничтожении экземпляра.


Не надо там ничего изобретать.

@WQ

Если для тебя так важно , чтобы очистка происходила одной функцией , просто помести cleartable в функцию freetable. Это как-то так должно быть:

Код

Sub THASHTABLE##_mk_##_mv_.freetable()
   
    cleartable()
   
    Deallocate(pArray)
   
End Sub


Ведь контейнеры - это не скомпилированная библиотека , ты в любой момент можешь вносить любые изменения.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
  • Страница 3 из 4
  • «
  • 1
  • 2
  • 3
  • 4
  • »
Поиск: