Dmitriy40Возможно, я не совсем точно выразился, а может, просто вы не так поняли. Вот код на жабе, ибо я не умею в с++:
// "Фигура":
import java.util.ArrayList;
import java.util.List;
public class Figure {
private String name;
private int invalidParents = 0;
private boolean isValid = true;
private List<Figure> children;
Figure(String name) {
this.name = name;
children = new ArrayList<>();
}
public boolean isValid() {
return isValid;
}
public int invalidParentsCount() {
return invalidParents;
}
public void introduceYourselfPlease() {
System.out.println("I am object " + name + ", is valid: " + isValid + ", invalid parents: " + invalidParents);
}
public void update(boolean fromParent) {
isValid = false;
for (int i = 0; i < children.size(); i++) {
children.get(i).update(true);
}
if (fromParent) {
invalidParents++;
}
}
public void parentRecalculated() {
invalidParents--;
}
public void recalculate() {
System.out.println("Object " + name + " is updated");
isValid = true;
for (int i = 0; i < children.size(); i++) {
children.get(i).parentRecalculated();
}
}
public void addChild(Figure child) {
children.add(child);
}
}
// Управляющий класс:
import java.util.ArrayList;
import java.util.List;
public class Demo {
static List<Figure> figures = new ArrayList<>();
static List<Figure> invalidFigures = new ArrayList<>();
public static void main (String[] args) {
Figure a = new Figure("A");
Figure b = new Figure("B");
Figure c = new Figure("C");
a.addChild(b);
a.addChild(c);
b.addChild(c);
figures.add(a);
figures.add(b);
figures.add(c);
printInfo();
a.update(false); // update by user
checkObjects();
System.out.println("User changed A");
printInfo();
recalculate();
System.out.println("Objects recalculated");
printInfo();
}
public static void recalculate() {
while (invalidFigures.size() > 0) {
for (int i = invalidFigures.size() - 1; i >= 0; i--) {
Figure f = invalidFigures.get(i);
if (f.invalidParentsCount() == 0) {
f.recalculate();
invalidFigures.remove(f);
}
}
}
}
public static void checkObjects() {
for (int i = 0; i < figures.size(); i++) {
if (!figures.get(i).isValid()) {
invalidFigures.add(figures.get(i));
}
}
}
public static void printInfo() {
for (int i = 0; i < figures.size(); i++) {
figures.get(i).introduceYourselfPlease();
}
}
}
Вот вывод:
Код:
I am object A, is valid: true, invalid parents: 0
I am object B, is valid: true, invalid parents: 0
I am object C, is valid: true, invalid parents: 0
User changed A
I am object A, is valid: false, invalid parents: 0
I am object B, is valid: false, invalid parents: 1
I am object C, is valid: false, invalid parents: 2
Object A is updated
Object B is updated
Object C is updated
Objects recalculated
I am object A, is valid: true, invalid parents: 0
I am object B, is valid: true, invalid parents: 0
I am object C, is valid: true, invalid parents: 0
Как видите, никаких дубликатов.
В принципе, у меня объекты сообщают своим потомкам о том, что они стали невалидны, но это с тем же успехом и точно так же можно делать и снаружи, разницы не будет вообще никакой (только список потомков объекта сделать публичным). А вот уже управление порядком пересчета - оно строго снаружи.
Теперь по пунктам:
Цитата:
у меня хватает статически выделенной памяти при любом количестве объектов, Вам же потребуется динамический список (можно и без него, но тогда перебирать все объекты);
Ничего не знаю по С++ и уж тем более про полный перебор списка, поэтому ничего не могу сказать.
Цитата:
у Вас нужен доступ к свойствам чужих объектов, у меня только к локальным и глобальным;
Непонятно, чего в этом плохого. Проблема издревле решается через геттеры и сеттеры, все так делают (и я так сделал) и ни один процесс(ор) пока от этого не умер.
Цитата:
у меня (и видимо ТС хотел) всё сделано на сигналах между объектами (и тройке статических глобальных переменных), у Вас же централизованно;
Я ж говорю - MVC! Рекомендации лучших
собаководов специалистов по ООП.
Цитата:
как следствие у меня можно обработку объектов параллелить (с атомизацией доступа лишь к двум глобальным переменным), у Вас поток выполнения похоже принципиально должен быть один.
В общем случае и в теории - наверно да, а на практике у нас тут большая куча объектов с непойми какими зависимостями между ними, и все равно как-то надо управлять порядком пересчета, чтобы не было долгих ожиданий, когда параллельный процесс досчитает родителя. Если у вас в С++ с системой "на сигналах" можно сказать компилятору "посчитай всю эту кучу в 4 потока", и он посчитает без лишних ожиданий, то я снимаю шляпу, застываю в немом восхищении и досрочно потихоньку ползу в сторону дома престарелых. Хотя что-то мне подсказывает, что так и так придется писать свой менеджер обработки этой кучи, и большую часть времени потоки будут ждать друг друга.
-- 14.08.2020, 15:54 --Думаю Вам надо было тоже разделить фазы инвалидации всех возможных объектов (и подсчёта родителей каждого) и их пересчёта. Ровно как и я ...
Я предлагал "однопоточную" идею, там нет никаких фаз. Пока инвалидация не закончится, пересчет не начнется.