Тестирование разных контейнеров и другая болтовня
|
|
zamabuvaraeu | Дата: Понедельник, 17.01.2022, 11:02 | Сообщение # 16 |
Подполковник
Группа: Друзья
Сообщений: 149
Статус: Offline
| Может быть список у них в виде массива реализован? Для виндоуз: может быть вместо функции Allocate попробовать частную кучу HeapCreate+HeapAlloc с флагом HEAP_NO_SERIALIZE.
|
|
| |
haav | Дата: Понедельник, 17.01.2022, 11:13 | Сообщение # 17 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Вчера , когда уже отключил компьютер и ложился спать , мне пришло осознание. Нет никаких чудес со связанным списком, просто: 1) я компилировал с опцией -exx (то есть закладывал в код по сути отладку). Если компилировать без этого , то скорость пуриковского связанного списка быстрее лишь в 1.5 раза. Это уже не в 4 раза!!! 2) я уже понял , что классическая схема создания списка здесь неуместна. Надо мыслить шире и начинать хитрить. И решение в голову пришло сразу же. Чтобы было понятнее, выглядеть список будет так:
Код pNode1 -> pNode2 -> .... | | array(31) array(31)
То есть в каждом элементе списка массив для данных. При создании например pNode1 сразу же выделяется память для массива. И следующие 30 добавлений память не выделяется , а просто данные заносятся в массив. Когда место в массиве заканчивается , создается новый элемент списка pNode2 опять же с массивом. Это значительно увеличит скорость по сравнению с классической схемой создания. Да эта реализация сложнее , но не настолько , чтобы ее невозможно было написать при желании. И в принципе вот набросок кода для добавления и получения данных:
Код type tData as Long
type T_NODE as TNODE ptr
type TNODE_M p(31) as tData bCurIndex as byte pRootNode as T_NODE ptr End Type
type TNODE pNext as TNODE ptr pPrev as TNODE ptr pArr as TNODE_M bFill as ULong bNextIndex as Byte End Type
type TLIST pFirst as TNODE ptr = 0 pLast as TNODE ptr = 0 declare sub add(pData as tData) declare sub insert(p as any ptr , pData as tData) declare function getFirst() as any ptr declare function getLast() as any ptr declare function getPrev(p as any ptr) as any ptr declare function getNext(p as any ptr) as any ptr declare function getValue(p as any ptr) as tData declare sub setValue(p as any ptr , pData as tData) End Type
sub TLIST.add(p as tData) dim pTemp as TNODE ptr if pFirst = 0 orelse pLast->bFill = &hFFFFFFFF then pTemp = callocate(sizeof(TNODE)) if pFirst then pLast->pNext = pTemp else pFirst = pTemp EndIf pLast = pTemp else pTemp = pLast EndIf pTemp->bFill = Bitset(pTemp->bFill, pTemp->bNextIndex) pTemp->pArr.p(pTemp->bNextIndex) = p pTemp->pArr.bCurIndex = pTemp->bNextIndex pTemp->pArr.pRootNode = cast(T_NODE ptr,pTemp) pTemp->bNextIndex+=1 End Sub
var t = timer
dim p as TLIST
for i as long = 0 to 10000000 p.add(i) Next
dim p0 as TNODE ptr = p.pFirst
while p0 for i as Long = 0 to 31 if bit(p0->bFill , i) then var w =p0->pArr.p(i) EndIf Next p0 = p0->pNext Wend
? Timer -t
Этот код уже уделывает пуриковский список примерно в 1.35 раза. Сейчас 17 против 23. Да , надо учесть , что еще будут простейшие функции-обертки , но не думаю , что это сильно изменит результат.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
DarkDemon | Дата: Понедельник, 17.01.2022, 17:45 | Сообщение # 18 |
Полковник
Группа: Друзья
Сообщений: 194
Статус: Offline
| Цитата haav ( ) Этот код уже уделывает пуриковский список примерно в 1.35 раза. Стас, качественный кастом всегда быстрее. Про это уже говорил кстати, что если всё кастом и если он написан не на отвали то в среднем софтина, долбя по целевой задаче, будет работать быстрее.
|
|
| |
haav | Дата: Понедельник, 17.01.2022, 22:13 | Сообщение # 19 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Цитата zamabuvaraeu ( ) Может быть список у них в виде массива реализован?
Не , не думаю. Это было бы крайне неэффективно в плане скорости , когда происходит вставка и удаление.
Цитата zamabuvaraeu ( ) Для виндоуз: может быть вместо функции Allocate попробовать частную кучу HeapCreate+HeapAlloc с флагом HEAP_NO_SERIALIZE.
Я же тестирую на линуксе.
Цитата DarkDemon ( ) Стас, качественный кастом всегда быстрее. Про это уже говорил кстати, что если всё кастом и если он написан не на отвали то в среднем софтина, долбя по целевой задаче, будет работать быстрее.
Леха , я это хорошо понимаю. Сколько раз нужно было внедрять в свои программы какие-то уже написанные универсальные куски кода, которые казалось бы работают хорошо. Сначала вроде берешь их , но потом понимаешь, что там надо что-то убрать , что-то добавить , что-то изменить и в итоге от начального куска остается призрак.
--------------
Что касается списков , то в принципе я добился того результата , который уже не хуже пуриковского. С обвесками скорость упала немного , но он сопоставима.
Код Мой лист: с обертками 0.258 (расход памяти 0.6% от 16GB) без оберток 0.184 (расход памяти 0.6% от 16GB)
purebasic list: 0.271 (расход памяти 1.9% от 16GB)
Дописывать вряд ли буду , не в этом была цель. Просто сделал себе вызов достигнуть скорости работы пуриковского списка. Непонятно только, почему пуриковский список жрет памяти в три раза больше чем мой. Вроде размер данных , отсылаемый в список , один и тот же (8 байт).
Код выкладываю напоследок. Сразу скажу , что почти не тестировал на ошибки. Некоторые функции вообще даже не пробовал , просто написал по наитию. Но ниже для интересующихся поясню , как можно реализовать удаление и вставку данных. Может можно что-то и лучше придумать , но мне уже лень. И так вот код:
Код type tData as Integer
type T_NODE as TNODE ptr
type TNODE_M p as tData End Type
type TNODE_CUR extends TNODE_M pRoot as T_NODE ptr End Type
type TNODE pNext as TNODE ptr pPrev as TNODE ptr pArr(31) as TNODE_M bFill as ULong bNextIndex as Byte End Type
type TLIST pFirst as TNODE ptr pLast as TNODE ptr pCurent as TNODE_CUR iCurentIndex as Long declare sub add(pData as tData) declare sub insert(pData as tData) declare function getFirst() as any ptr declare function getLast() as any ptr declare function getPrev() as any ptr declare function getNext() as any ptr declare function getValue() as tData declare sub setValue(pData as tData) declare sub resetList() End Type
sub TLIST.add(p as tData) dim pTemp as TNODE ptr = any if pFirst = 0 orelse pLast->bFill = &hFFFFFFFF then pTemp = callocate(sizeof(TNODE)) if pFirst then pLast->pNext = pTemp else pFirst = pTemp EndIf pLast = pTemp else pTemp = pLast EndIf iCurentIndex = pTemp->bNextIndex pTemp->bFill = Bitset(pTemp->bFill, iCurentIndex) pTemp->pArr(iCurentIndex).p = p pCurent.pRoot = cast(T_NODE ptr, pTemp) pCurent.p = p pTemp->bNextIndex+=1 End Sub
sub TLIST.insert(pData as tData) End Sub
function TLIST.getFirst() as any ptr if pFirst then for i as Long = 0 to 31 if bit(pFirst->bFill , i) then return @(pFirst->pArr(i)) EndIf Next EndIf End Function
function TLIST.getLast() as any ptr if pLast then for i as Long = 31 to 0 step -1 if bit(pLast->bFill , i) then return @(pLast->pArr(i)) EndIf Next EndIf End Function
function TLIST.getPrev() as any ptr if pCurent.pRoot then dim as TNODE ptr pRootNode = any dim iStartIndex as ULong = any if iCurentIndex = 0 then pRootNode = cast(TNODE ptr , pCurent.pRoot)->pNext iStartIndex = 32 else iStartIndex = iCurentIndex pRootNode = cast(TNODE ptr , pCurent.pRoot) EndIf do for i as Long = 31 to iStartIndex-1 step-1 if bit(pRootNode->bFill , i) then pCurent.pRoot = cast(T_NODE ptr , pRootNode) pCurent.p = pRootNode->pArr(i).p iCurentIndex = i return pCurent.pRoot EndIf Next iStartIndex = 0 pRootNode = pRootNode->pNext loop while pRootNode endif End Function
function TLIST.getNext() as any ptr if pCurent.pRoot then dim as TNODE ptr pRootNode = any dim iStartIndex as ULong = any if iCurentIndex = 31 then pRootNode = cast(TNODE ptr , pCurent.pRoot)->pNext iStartIndex = -1 else iStartIndex = iCurentIndex pRootNode = cast(TNODE ptr , pCurent.pRoot) EndIf do for i as Long = iStartIndex+1 to 31 if bit(pRootNode->bFill , i) then pCurent.pRoot = cast(T_NODE ptr , pRootNode) pCurent.p = pRootNode->pArr(i).p iCurentIndex = i return pCurent.pRoot EndIf Next iStartIndex = 0 pRootNode = pRootNode->pNext loop while pRootNode endif End Function
function TLIST.getValue() as tData if pCurent.pRoot then return pCurent.p End Function
sub TLIST.setValue(pData as tData) if pCurent.pRoot then pCurent.p = pData End sub
sub TLIST.resetList() if pFirst then for i as Long = 0 to 31 if bit(pFirst->bFill , i) then iCurentIndex = i pCurent.pRoot = cast(T_NODE ptr,pFirst) pCurent.p = pFirst->pArr(i).p exit for EndIf Next EndIf End Sub
var t = timer ' dim p as TLIST
for i as long = 0 to 10000000 p.add(i) Next
p.resetList()
do var v = p.getValue() '? "value" , V Loop while p.getNext()
? timer -t sleep
А это пуриковский код:
Код OpenConsole() StartTime.q = ElapsedMilliseconds()
NewList MyList()
For i=0 To 10000000
AddElement(MyList()) MyList() = i
Next
ResetList(MyList()) While NextElement(MyList()) f = MyList() Wend
Print(Str(ElapsedMilliseconds() - StartTime))
Удаление делается очень просто. Для первой и последней ячейки массива (их я напомню 32 для каждого Node ) просто обнуляем нужный бит в переменной bFill. Реализация построена так , что будет пропускать эти ячейки. Для других ячеек, просто сдвигать данные в цикле. Если окажется так , что все ячейки массива пустые , то Node так же удаляем. Что касается вставки. Если нужно вставлять в начало или в конец любого массива , то тут просто создаем новый Node c новым массивом , записываем в нулевую ячейку данные и устанавливаем его текущим. И так же конечно связываем новый Node c предыдущим и следующим Node.
Если нужно вставить в середину массива... , то покажу на примере:
1 Node и его массив {0,1,2,3,4,5,6,7.....} 2 Node и его массив {0,1,2,3,4,5,6,7.....}
Нужно вставить данные после 4 ячейки 1 Node. Должно получится так:
1 Node и его массив {0,1,2,3,4,new,5,6,7.....} Сначала копируем последнюю ячейку в новый массив, потом просто переносим остальные ячейки вперед в цикле. new Node и его массив {31,.....} <- сюда копируем последнюю ячейку из первого массива. 2 Node и его массив {0, 1,2,3,4,5,6,7.....} здесь ничего не трогаем
или так будет быстрее (в общем определять какая ячейка ближе и где меньше данных переносить): new Node и его массив {0,.....} <- сюда копируем первую ячейку из первого массива. 1 Node и его массив {1,2,3,4,new,5,6,7.....} Сначала копируем первую ячейку в новый массив, потом просто переносим остальные ячейки назад в цикле. 2 Node и его массив {0, 1,2,3,4,5,6,7.....} здесь ничего не трогаем
Ну и конечно нужно будет связать Nodes между собой.
Наверняка , при написании , могут возникнуть и другие идеи, я лишь озвучил ту, которая первая пришла в голову.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
haav | Дата: Понедельник, 17.01.2022, 22:16 | Сообщение # 20 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Если кто-то будет тестировать , не забываем в пурике отключать дебаггер , а в FB компилировать просто без опций
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
haav | Дата: Среда, 19.01.2022, 13:40 | Сообщение # 21 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Нет , все таки пуриковский лист какая-то фантастика. Ведь по сути у них скорость:
1) вставка примерно как у связанного списка 2) добавление быстрее чем в связанных списках 3) удаление как в связанных списках 4) доступ как у массивов по индексу. Понятно , что данные не лежат упорядочено как в массиве , но скорость получения данных сопоставима!
Как Фреду удалось то , что кажется невозможным? Ему что , код списков инопланетяне подсказали?
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
WQ | Дата: Среда, 19.01.2022, 20:56 | Сообщение # 22 |
Полковник
Группа: Проверенные
Сообщений: 215
Статус: Offline
| haav
Вроде списки из этой темы довольно быстрые, по крайней мере по сравнению с другими примерами на freebasic
https://www.freebasic.net/forum....p260519
|
|
| |
haav | Дата: Среда, 19.01.2022, 21:34 | Сообщение # 23 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Цитата WQ ( ) Вроде списки из этой темы довольно быстрые, по крайней мере по сравнению с другими примерами на freebasic Примеры 2 и 3 созданы по классической схеме, то есть добавление , удаление , вставка будут более менее быстрыми, если заранее известен указатель. В пурике есть мгновенная индексация и можно очень быстро например изменить или удалить каждый 10 элемент от начала. Кроме того , добавление в конец в пурике раза в 1.5 быстрее. Конечно , если не нужна частая вставка и удаление , а просто нужно заполнить и получать доступ , то вообще можно использовать вектор из моих контейнеров , он по скорости добавления обгонит пуриковский список почти в 2 раза. Но если нужна частая вставка и удаление (особенно вначале или в середине) , то тут по времени вектор окажется в глубокой заднице.
Что касается 1 примера , то достаточно только посмотреть на этот отрывок кода:
Код function simple_list.find(value as data_type) as integer for i as integer = 0 to ubound(myData) if myData(i) = value then return i next return -1 'not found end function
как сразу станет все понятно. Эта обычный линейный перебор. Уж лучше тогда деревья или хеш таблица. Списки не для того , чтобы линейно перебирать всю коллекцию в поисках ключа. Конечно для не критических участков и так сойдет. Мне на самом деле больше интересно , как Фред сумел скрестить быстроту доступа массива и скорость добавления\вставки\удаления связанных списков в одно целое.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
haav | Дата: Четверг, 20.01.2022, 08:24 | Сообщение # 24 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Блин , вот ведь я дурень. Нет никаких чудес и нет никакого мгновенного доступа у пуриковских списков. Я уж думал , что такое реально возможно с помощью какого нибудь хитрого индексирования. Переоценил я человеческие возможности. Все как всегда , просто были удобные примеры , да и я стормозил. Если же реально сделать постоянные перемещения по индексам , то список ведет себя ожидаемо с линейной зависимостью. Вот простейший пример в котором просто список заполняется миллионом элементов , а потом при получении всего то 10000 значений из разных индексов , список тратит более 10 секунд:
Код Dim m(1) m(0) = 421111 m(1) = 763000
NewList MyList()
For i=0 To 1000000 AddElement(MyList()) MyList() = i Next
StartTime.q = ElapsedMilliseconds()
For i=0 To 5000 For j = 0 To 1 SelectElement(MyList() , m(j)) p = MyList() Next Next
MessageRequester("" , Str(ElapsedMilliseconds() - StartTime))
Ну вот в общем-то и все , дальнейшие ковыряния уже не интересны.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
WQ | Дата: Суббота, 26.03.2022, 23:50 | Сообщение # 25 |
Полковник
Группа: Проверенные
Сообщений: 215
Статус: Offline
| haav
У HashTable нет возможности обхода всей таблицы?
|
|
| |
laser | Дата: Воскресенье, 27.03.2022, 01:45 | Сообщение # 26 |
Лейтенант
Группа: Пользователи
Сообщений: 57
Статус: Offline
| Цитата haav ( ) нет никакого мгновенного доступа у пуриковских списков. Я уж думал , что такое реально возможно с помощью какого нибудь хитрого индексирования. В PB стандартный [url=https://ru.wikipedia.org/wiki/Связный_список#Двусвязный_список_(двунаправленный_связный_список)]двусвязный список[/url]. В каждом элементе храниться ссылка на предыдущий и следующий элемент. Кроме того в списке хранится ссылка на начальный, текущий и конечный элемент. Чтобы найти элемент нужно пройтись по списку. Если выбирать элементы, близкие к начальному, текущему или конечному, поиск производит очень быстро.Код DisableDebugger Dim m(3) m(0) = 200 m(1) = 100 m(2) = 1000000-100 m(3) = 1000000-200
NewList MyList()
For i=0 To 1000000 AddElement(MyList()) MyList() = i Next
StartTime.q = ElapsedMilliseconds()
For i=0 To 5000 For j = 0 To 3 SelectElement(MyList() , m(j)) p = MyList() Next Next
MessageRequester("" , Str(ElapsedMilliseconds() - StartTime))
Также последовательной перебор списка производится быстро.Код DisableDebugger
NewList MyList()
For i=0 To 1000000 AddElement(MyList()) MyList() = i Next
StartTime.q = ElapsedMilliseconds()
ForEach MyList() p = MyList() Next
MessageRequester("" , Str(ElapsedMilliseconds() - StartTime))
Сообщение отредактировал laser - Воскресенье, 27.03.2022, 01:46 |
|
| |
haav | Дата: Воскресенье, 27.03.2022, 07:31 | Сообщение # 27 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Цитата WQ ( ) У HashTable нет возможности обхода всей таблицы?
Я даже не думал , что это может быть нужно. Но вообще это не проблема , ты всегда можешь добавить процедуру перечисления. Вот пример:
Код #include "HashTable.bi"
MHashTemplate(Zstring , Zstring)
Dim As THASHTABLEzstringzstring Ptr pTable = New THASHTABLEzstringzstring
sub EnumTable(pTable as THASHTABLEzstringzstring Ptr) For i As Long = 0 To pTable->iSize If pTable->pArray[i].pszKey Then If pTable->pArray[i].iFdelete = 0 Then ? *(pTable->pArray[i].pszValue) Endif If pTable->pArray[i].pList Then Dim As TLISTzstringzstring Ptr pTemp pTemp = pTable->pArray[i].pList->pFirst While pTemp ? *(pTemp->pszValue) pTemp = pTemp->P Wend Endif Endif Next End Sub
pTable->insert("Key1" , "Value1") pTable->insert("Key2" , "Value2") EnumTable(pTable) pTable->cleartable() pTable->freetable() Sleep
Цитата laser ( ) В каждом элементе храниться ссылка на предыдущий и следующий элемент. Кроме того в списке хранится ссылка на начальный, текущий и конечный элемент. Чтобы найти элемент нужно пройтись по списку. Если выбирать элементы, близкие к начальному, текущему или конечному, поиск производит очень быстро.
Да , я это понял , но не сразу. Индексацию в своем списке я переписал тоже по этому принципу.
Кстати laser , в линуксе Фред сделал многопоточность для Gui? Для w9 я нашел способ использовать многопоточность (пример ниже). Если многопоточности нет , то можно ее прикрутить как в примере ниже? Если лень запускать FB код , то вкратце это работает так: в Textgadget меняется текст с помощью 2 дополнительных потоков и при клике мыши по гаджету текст так же меняется. То есть получается текст меняется в 3 потоках и не конфликтует.
Пример:
Код #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=Waitevent() If Event= Eventclose Then End If Event=Eventgadget Then Select Case Eventnumber Case 1 sValue = "main thread" Setgadgettext(1,sValue) End Select Endif Loop
gdk_threads_leave()
End
Function thSub Cdecl(p As Integer) As Any Ptr Do Sleep(Rnd*1000) gdk_threads_enter() If p = 1 Then sValue = "thread 1" Else sValue = "thread 2" Endif Setgadgettext(1 , sValue) gdk_flush() gdk_threads_leave() Loop Return 0 End Function
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
haav | Дата: Воскресенье, 27.03.2022, 09:55 | Сообщение # 28 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Че-то какая-то ерунда творится с редактированием сообщений. После редактирования все теги путаются. Уже два раза редактировал и кое-как сумел донести то , что хотел. Уже не рискнул дополнительно вносить в прошлое сообщение текущие строчки . Лучше отдельно , а то опять весь текст исправлять в отдельном редакторе. Возможно это из-за индексации в коде , вроде pArray[i].pszKey.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
laser | Дата: Воскресенье, 27.03.2022, 17:21 | Сообщение # 29 |
Лейтенант
Группа: Пользователи
Сообщений: 57
Статус: Offline
| Цитата haav ( ) в линуксе Фред сделал многопоточность для Gui? Нет. Только в лине 3 подсистемы (gtk2, gtk3 и qt). В маке свой GUI. Это надо тестить много платформ и подсистем на совместимость с многопоточностью. Можно сделать проще и на 100% рабочим на всех платформах.Код CompilerIf #PB_Compiler_Thread=0 CompilerError "Please enable treadsafe" CompilerEndIf
Enumeration #PB_Event_FirstCustomValue #EventGadgetUpdate EndEnumeration
Procedure Thread(Value) For i=1 To 10 PostEvent(#EventGadgetUpdate, 0, 2, 0, i) Delay(1000) PostEvent(#EventGadgetUpdate, 0, 3, 0, i*10) Delay(1000) Next PostEvent(#PB_Event_CloseWindow, 0, 0) ; Закрываем форточку а вместе с ней прогу. EndProcedure
OpenWindow(0, 200, 200, 100, 100, "PostEvent") TextGadget(2, 10, 10, 180, 20, "") TextGadget(3, 10, 30, 180, 20, "")
CreateThread(@Thread(), 0)
Repeat Event = WaitWindowEvent() Select Event Case #EventGadgetUpdate Gadget = EventGadget() If IsGadget(Gadget) SetGadgetText(Gadget, Str(EventData())) EndIf EndSelect Until Event = #PB_Event_CloseWindow
Из потока отправляться событие с номером гаджета и данными. В основном потоке записывается в гаджет.
Цитата haav ( ) То есть получается текст меняется в 3 потоках и не конфликтует. Точно не конфликтует? В коде глобальная переменная sValue общая для всех потоков. Глюк будет, но через случайное время. Сделай переменную локальной или поточной (аналог Threaded в PB).
Сообщение отредактировал laser - Воскресенье, 27.03.2022, 17:22 |
|
| |
haav | Дата: Воскресенье, 27.03.2022, 18:22 | Сообщение # 30 |
Генералиссимус
Группа: Администраторы
Сообщений: 1363
Статус: Offline
| Цитата laser ( ) Точно не конфликтует? В коде глобальная переменная sValue общая для всех потоков. Глюк будет, но через случайное время.
Я конечно не уверен на 100% , но вроде эти штуки:
gdk_threads_enter , gdk_threads_leave
как раз и нужны для синхронизации. Понятно , что в данном случае эта переменная не нужна глобальной , я ее специально сделал , чтобы подчеркнуть , что в коде присутствует синхронизация.
Цитата laser ( ) Из потока отправляться событие с номером гаджета и данными. В основном потоке записывается в гаджет.
Наверное именно для PostEvent (а может и не только для нее) все таки синхронизация внутренне выполняется.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
|