А почему вместо objects не считать сигналы done? И поясните, пожалуйста, про разделение доступа.
Да, можно и done считать, в той же переменной signals, даже на одну глобальную переменную меньше будет. Но не будет общего числа затронутых объектов, если оно зачем-то нужно (в signals лишь мгновенное количество, не общее).
К глобальным переменным signals и objects (если она реализуется) из всех затронутых объектов осуществляется доступ не только на чтение, но и на запись, а в многопоточной системе надо исключать одновременный доступ на запись (и модификацию) к любой общей/глобальной переменной. Семафорами, критическими секциями или много чем ещё можно, включая и встроенные средства языка. Но запись (точнее модификация) должна быть атомарна, т.е. только от одного (но любого) объекта. Кстати именно поэтому у меня везде (надеюсь) сначала увеличиваются счётчики и лишь потом уменьшаются (на единицу для поглощения входящего сигнала), или увеличиваются сразу на скорректированное значение. Т.е. ни в какой момент времени счётчик не может обнулиться если волна не закончилась.
Переменную ObjectStart защищать нет необходимости, в неё пишется или до начала всего процесса, или по его полному завершению, и всегда только одним объектом (но в начале и в конце разными). В каком бы порядке объекты не выполнялись, совместиться эти операции не могут и потому защита не обязательна.
Если вместо objects считать сигналы done, не решит ли это проблему гонок?
Проблема гонок не связана с повторной модификацией объекта до окончания просчёта всей сцены, засада в разном времени прохождения сигналов invalidate и done до каких-то объектов вдали от начального. И может получиться что сигнал done придёт ДО прихода сигнала invalidate, по приходу же последнего тогда произойдёт опасная чушь. Лишь поэтому надо ждать окончания волны invalidate и лишь потом запускать волну done.
В этом случае он будет ждать, пока придут сигналы done от первого и второго обновлений, а только потом обновится сам.
Хм, а ведь да, может получиться, даже ничего менять не надо, не могу придумать пример когда это не сработает. Выходит тут даже можно сколько угодно объектов модифицировать в любое время, даже во время пересчёта предыдущего состояния. Надо только будет снова разделить счётчики сигналов invalidate и done. И вместо одной переменной ObjectStart сделать список таких объектов, которым и рассылать сообщения done для начала пересчёта при обнулении signals. Или ждать окончания волны invalidate в запускающей процедуре ModifyObject() и лишь потом в ней же запускать волну done (но мне так не понравилось, не люблю пустых циклов ожидания, занимающих проц на 100% на неопределённое время).
Ещё будет полезно в обработке сигнала done первым делом проверить My.local на ноль и если да, то ничего не делать (кроме уменьшения счётчика сигналов done).
О как, оказывается код даже более универсальный получился чем думал.
-- 16.08.2020, 00:50 --george66Вообще, не считайте мой вариант кода готовым решением, там вполне могут быть глюки, он писан лишь для иллюстрации идеи двух волн сигналов (потому что словами объяснение оказалось в разы запутаннее, несколько раз почти полностью набирал и полностью переделывал и наконец забил и оформил в виде кода), лучше разберитесь на уровне идеи, а тогда код напишется чуть ли не сам.