Russian Qt Forum
Июнь 16, 2024, 02:49 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Глобальные объекты - реализация  (Прочитано 7599 раз)
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« : Май 08, 2015, 17:24 »

Привет. Зашел в тупик. Задача такая, есть экзешник, есть несколькол либ (которые прилинкованы к экзешнику) и есть несколько либ-плагинов, которые могут подгружаться, выгружаться.
Нужно для всех этих едениц предоставить некие глобальные объекты. При этом все эти классы объектов находятся в либах и/или плагинах. Задача экзешника загрузить плагины их настроить и запустить.
Из каджого плагина и каждой либы нужно иметь доступ к глобальным объектам.
Испробовал несколько решений но так толком и ничего не сделал внятного. Остановился на синглтонах. Но есть проблема, что некоторые глобальные объекты завится от других. Нужно корректно их инициализировать и финализировать. С синглтонами с инициализацией все понятно, а вот финализация происходит после деструктора главного окна, и в глобальных объектах перед разрушением нет уже корректных указателей на ГУИ компоннеты и прочие данные. Т.е. надо что бы сингтоны которые созданы в либах, удалялись до деструктора главного окна. Как быть? Таких классов порядка 15...
« Последнее редактирование: Май 08, 2015, 19:39 от Fregloin » Записан
Bepec
Гость
« Ответ #1 : Май 09, 2015, 12:04 »

Непонятна проблема. Закрывайте всё в НАЧАЛЕ деструктора главного окна.
Всё у вас будет, гуи висят, данные стоят, синглтоны спокойны.

PS или распишите проблему подробнее, а то непонятно Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Май 09, 2015, 13:11 »

Непонятна проблема. Закрывайте всё в НАЧАЛЕ деструктора главного окна.
Всё у вас будет, гуи висят, данные стоят, синглтоны спокойны.
А как он их "закроет" если они напр шаред пойнтеры?
Записан
Bepec
Гость
« Ответ #3 : Май 09, 2015, 13:18 »

Удалит все объекты, которые на них ссылаются.
Это же прописные истины, разве нет?

Тем более что упоминается не закрытие, а финализация. Не совсем понятно что это значит, но видимо сохранение данных. А на этот случай должен быть слот/функция/метод.

PS тем более дальнейшая судьба шаред поинтеров нас не интересует. Нас интересует финализация - сохранение результатов перед закрытием программы.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Май 09, 2015, 14:03 »

Удалит все объекты, которые на них ссылаются.
Это же прописные истины, разве нет?
Разве нет.
Код
C++ (Qt)
std::shared_ptr <MyClass> m_data;
Удалять-то нечем, нужно чтобы область видимости m_data закончилась. А если m_data была куда-то скопирована, то и та область тоже и.т.д

С синглтонами с инициализацией все понятно, а вот финализация происходит после деструктора главного окна, и в глобальных объектах перед разрушением нет уже корректных указателей на ГУИ компоннеты и прочие данные. Т.е. надо что бы сингтоны которые созданы в либах, удалялись до деструктора главного окна. Как быть? Таких классов порядка 15...
Что-то "не то". Сначала хотели/заявили что "синглтоны живы пока есть хоть один использующий". Теперь что-то не устроило и хотим переиграть - несолидно выходит Улыбающийся В чем сложности если обнулять "указатели на ГУИ" в синглтонах и вставить проверки на NULL?
Записан
Bepec
Гость
« Ответ #5 : Май 09, 2015, 15:26 »

Igors поднимите веки и отталкивайтесь не от моих мыслей, основанных на словах тсса, а на задаче, которую предлагает ТС.
Сначала изучите первое сообщение, потом второе и так далее.
Составьте цепочку суждений и поймите, что ваш вопрос возник из ниоткуда, ушёл в никуда, а мои утверждения стоят на словах тсса, аки на столбах.

PS когда же вы прекратите добавлять никому не нужные условия?
PPS мб стоит поднять тему и попросить создать раздел "обсуждение идеальных решений, алгоритмов и идей"? Вот в таком разделе ваши высказывания были бы полезны. А вот в решении практических задач - бессмысленны. Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #6 : Май 09, 2015, 16:26 »

Разве нет.
Код
C++ (Qt)
std::shared_ptr <MyClass> m_data;
Удалять-то нечем, нужно чтобы область видимости m_data закончилась.
Всегда можно сделать m_data.reset();

А если m_data была куда-то скопирована, то и та область тоже и.т.
И там сделать reset, но лучше их не куда не копировать, а получать указатель там где надо, через instance.
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #7 : Май 12, 2015, 10:56 »

Попытаюсь объяснить на пальцах ).
Вобщем есть объект, который отвечает за хранение неких логических объектов. По сути хеш таблица с кучей методов досутпа к элементам этой таблицы.
Есть объект, которых хранит указатели на элементы на сценах (сцен может быть несколько).
Есть объект, который хранит связи между логическими объектами и элементами на сцене.
Есть объект, который хранит контроллеры-обработчики, сущности отвечающие за отрисовку элементов на сцене в зависимости от состояний логчиеских объектов.
Еще куча глобальнных объектов, которые отвчеают за воспроизведение звуков, конфигурацию программы, и еще туева хуча таких объектов.
Часть глобальных объектов описана в одной либе, к которой линкуется экзешник. Часть таких объектов подгружается в плагинах.
Суть в том, что в любом месте проекта (т.е. как в исполняемом файле, так в любой либе, в любом классе проекта) нужно иметь удобный доступ к этим объектам.
В самом начале я хранил указатели на них в каждом классе, но это утомительно сопровождать, так как по сути:
-эти объекты (как я их назвал для себя менеджеры) существуют в единственном экземпляре
-они глобльны для каждого экземпляра программы
-могут добавляться новые.
Потом решил использовать шаблон Mediator. Хранил в хеш-таблице указатели на эти объекты по некоторым строковым константам. Но так же столкнулся с множеством неудобств, таких как
-нужно было хранить копии указателей на эти объекты, получать их и кастить
-баналаная опечатка могла не дать найти этот объект по ключу (позже решил это через public static const QString константу каждого класса менеджера)
-и еще куча мелких заморочек которые мешали спокойно жить.
Вот и пришел к выводу, что эти менеджеры по сути есть синглтоны.
Теперь по поводу их создания и удаления. Почему то в голову пришла идея, что каждый синглтон должен инициализироваться в своей библиотеке. Потому что есть подгружаемые плагины, и не хотелось бы явно указывать в конструкторе главного окна создания всех этих менеджеров. Но проблема в том, что порядок удаления обратный, и когда главное окно уже разрушено, вызываются
деструкторы менеджеров в своих либах. И конечно же вылетает сегментация, т.к. доступа к некоторым объектам уже нет (гуи и не только).
Так же есть менеджеры, которые зависят от других. Почти в каждом менеджере используется менеджер логических объектов, потому что вокруг них все и вращается по сути.
Сейчас пришла в голову мысля чтобы сделать один синглтон, который будет отвечать за создание и удаление менеджеров, он будет вызываться в конструкторе и деструкторе главного окна, и будет хранить фабрики остальных менеджеров. Фабрики будут создавать и инициализироваь нужные менеджеры а так же их финализировать и удалять. Посмотрю на сколько это будет удачное решение...
Записан
Bepec
Гость
« Ответ #8 : Май 12, 2015, 11:23 »

Вообще теперь непонятно ничего. Разве вы не можете вызвать деструкторы ДО разрушения главного окна?
Ведь все ваши проблемы именно из-за этого.

PS идея с менеджером как раз и решит эту проблему.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Май 12, 2015, 11:55 »

Фабрики будут создавать и инициализироваь нужные менеджеры а так же их финализировать и удалять. Посмотрю на сколько это будет удачное решение...
Какое-то чуждое словечко "финализировать" (явно с жабьим уклоном) Улыбающийся Давать советы здесь сложно, но вот что бросается в глаза

- хотим получать синглтон по первому требованию (если его еще нет, сам создается)
- синглтон отслеживает счетчик ссылок (клиентов), когда он обнулится, синглтон само-ликвидируется

Это нормально, по существу так же работает и шаред пойнтер (хотя он и не обязан быть синглтоном). НО это предполагает что сами мы (руками, delete) ничего не удаляем. Так нельзя, вся система теряет смысл, придется очень мучительно отслеживать всех кто может еще пользовать удаляемые данные - явный говнокод.

Очень сомнительно чтобы менеджеры удалялись ДО главного окна, как Вы хотите. Когда начинает выполняться код деструктора, объект еще полностью валиден - и значит может потребовать нужный синглтон. Предполагать что "такого у меня не будет" недальновидно. Первое что приходит в голову - не удалять, а деактивировать синглтоны. Хоть завести флажок "inDestruct" по которому все обращения синглтонов к эл-там UI блокируются. Qt делает подобным образом для qApp. Да, это немало проверок (и/или ассертов) в коде всех синглтонов - но лучшего может просто не оказаться.

По поводу нового увлечения фабриками - в данном случае неясно что Вы хотите от них получить. Как только Вы откажетесь от подхода в стиле шаред пойнтера - Вам придется отслеживать все связки руками (ну его нафиг).


Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #10 : Май 12, 2015, 13:45 »

я делал на QSharedPointer, но у меня получались рекурсивные связи между синглтонами, и некоторые не удалялись, так как от них зависили другие, а другие зависили от первых...
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #11 : Май 12, 2015, 14:02 »

я делал на QSharedPointer, но у меня получались рекурсивные связи между синглтонами, и некоторые не удалялись, так как от них зависили другие, а другие зависили от первых...
Используйте QSharedPointer только у владельца объекта, а в остальных случаях для хранения указателя используйте QWeakPointer.

И если вы уже вляпались в большую гадость под названием синглетон, так и не храните циклические ссылки друг на друга, а получайте их через instance.
« Последнее редактирование: Май 12, 2015, 14:09 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Май 12, 2015, 14:13 »

я делал на QSharedPointer, но у меня получались рекурсивные связи между синглтонами, и некоторые не удалялись, так как от них зависили другие, а другие зависили от первых...
Ну это (циклическая зависимость, dead-lock) разруливать придется в любой системе. И не суть как называется и на чем конкретно реализовано - shared_ptr, QSharedPointer или самопальный синглтон, смысл везде один.

Вообще как-то вяло. Типа "ну вот, делал на шаред - что-то не связалось. Попробую на фабриках". Ну опять "что-то не свяжется", так и бум все "пробывать" Улыбающийся Мне кажется нужно выбрать путь и верить что он правильный, пока жизнь не покажет обратное.
Записан
Bepec
Гость
« Ответ #13 : Май 12, 2015, 14:19 »

На мой взгляд у вас проблема в архитектуре, а не в каких то мифических "удаляется раньше позже".

Последуйте совету Igors и выберите архитектуру, сделайте наброски алгоритмов, и только после того как сами всё поймёте, начинайте кодить.

PS Если не видеть полную картинку, а программировать частями, получится фигня. Хоть какой то план надо иметь.
Записан
Akon
Гость
« Ответ #14 : Май 13, 2015, 11:12 »

Fregloin: попытйтсь дать фомальное описание с вовлечением мин. кол-ва объектов, а то сложно понять.

Цикл. зав-ти нужно разруливать. На архитектурном уровне могу дополнительно отметить следующие общие рекомендации:
1. Inversion of Control (IoC) - по сути банальное дробление объектов до независимых частей. Если А зависит от Б, то в Б зависимая часть выделяется в третий объект С, в результате А и Б зависят от С, но не друг от друга.
2. Позднее разрешение указателей, т.е. на некоторых ранних стадиях создания/загрузки системы вместо указателей используются их ID, далее они разрешаются.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.214 секунд. Запросов: 22.