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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Resolve Links  (Прочитано 13642 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Февраль 11, 2013, 12:24 »

Добрый день

Есть файл сериализованных данных организованный так

- контейнер объектов класса A
- контейнер объектов класса B
- и.т.д

При этом любой из объектов любого класса может иметь члены-указатели/ссылки на другие объекты, хотя сам его не создает и не удаляет. Также объекты не связаны никаким отношением parent-child, просто один объект использует другой.

Проблема в том что восстановить указатели немедленно (сразу при чтении) мы не можем (не на что пока указывать, тот объект еще не прочитан). Вопросы к обсуждению

- не надумана ли эта проблема?
- как лучше организовать восстановление указателей?

Спасибо
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #1 : Февраль 11, 2013, 12:46 »

- не надумана ли эта проблема?
Ну как сказать, она довольно просто реализуется

- как лучше организовать восстановление указателей?
Зависит от контейнеров:
* для контейнеров с индексным доступом - вместо указателя сохранять индекс в контейнере. Сохранять строго в той же последовательности, как они хранятся.
* для контейнеров с ключами - сохранять ключ.

После загрузки всех объект, получать указатели объектов по индексу/ключу.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Февраль 12, 2013, 12:04 »

Здесь "контейнер" не значит что сами объекты хранятся в контейнере. Объекты создаются с помощью new, хранится только напр вектор указателей.

Да, вариант с индексом самый естественный/очевидный, именно так у меня и сделано. Вернее, еще тем программистом работу которого я продолжаю, Минус тот что объекты невалидны до тех пор пока ссылки не разрешены.
Код
C++ (Qt)
void A::DoSomething( void )
{
..
if (mData != NULL)   // mData "вообще нет" или "пока нет"?   :-)
..
}
Приходится городить так
Код
C++ (Qt)
class A {
...
int mIndexIO; // да, это поле только для IO, но иначе еще дороже
B * mData;
};
 
Восстановление ссылок также довольно унылая процедура
Код
C++ (Qt)
for (size_t i = 0; i < container_A.size(); ++i)
container_A[i]->ResolveLinks();
 
Ну и уже набежало больше 2 десятков таких циклов.  Вот обдумываю как это улучшить
Записан
Akon
Гость
« Ответ #3 : Февраль 12, 2013, 13:17 »

Сдается мне, вы все ходите вокруг сериализации. А чем boost::serialization не подошел? Избавил бы от многих велосипедов.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #4 : Февраль 12, 2013, 14:18 »

Здесь "контейнер" не значит что сами объекты хранятся в контейнере. Объекты создаются с помощью new, хранится только напр вектор указателей.
И что это поменяло? Не имеет значения, что хранится в контейнере, сами объекты или указатели на них. От этого их индекс не меняется. Улыбающийся

Да, вариант с индексом самый естественный/очевидный, именно так у меня и сделано. Вернее, еще тем программистом работу которого я продолжаю, Минус тот что объекты невалидны до тех пор пока ссылки не разрешены.
А у вас в системе этими объектами кто-то может начать пользоваться до завершения их загрузки? Наверное из других потоков.  Подмигивающий

Приходится городить так
Код
C++ (Qt)
int mIndexIO; // да, это поле только для IO, но иначе еще дороже
};
 
Повторно сохраняя индекс объекта в контейнере в самом объекте.... Да, вас ждет еще куча проблем впереди. Улыбающийся
« Последнее редактирование: Февраль 12, 2013, 14:21 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Февраль 12, 2013, 14:42 »

Сдается мне, вы все ходите вокруг сериализации. А чем boost::serialization не подошел? Избавил бы от многих велосипедов.
В стремлении "избежать всяких велосипедов" легко перейти грань и оказаться в роли бездумного пользователя чужих классов. Конечно с бустом этой проблемы не будет - но так будут другие. Напр не потеряю ли я контроль формата файла данных ("архива" по-бустовски)? Так я худо-бедно но могу грузить данные выборочно (напр по ключу), т.к. ID мне известно. А что я буду делать отдав это могучему дусту?

Повторно сохраняя индекс объекта в контейнере в самом объекте.... Да, вас ждет еще куча проблем впереди. Улыбающийся
Ну так за чем же дело встало? Слушаю Вас как сделать лучше  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #6 : Февраль 12, 2013, 15:19 »

Ну так за чем же дело встало? Слушаю Вас как сделать лучше  Улыбающийся
Вот смотрите: сейчас этот класс, который вы раньше и сериализовать не думали, должен знать о контейнерах, уметь получать индексы по указателям и наоборот... короче кучу всего, что ему не только уметь делать не надо, а даже знать про это. Я бы воспользовался внешним классом/функцией для сериализации этих объектов. А вот объект этого класса/функция пусть знает про контейнеры, умеет получать индексы и.д., короче читает/пишет эти объекты в поток.
 
« Последнее редактирование: Февраль 12, 2013, 15:57 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Февраль 12, 2013, 16:46 »

Я бы воспользовался внешним классом/функцией для сериализации этих объектов. А вот объект этого класса/функция пусть знает про контейнеры, умеет получать индексы и.д., короче читает/пишет эти объекты в поток.
Прошу исполнить
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Февраль 12, 2013, 16:56 »

Прошу исполнить

Код
C++ (Qt)
void saveObjectA( ostream &os, const A &obj, const Coll<B*> collB )
{
   os << obj.data1 << obj.data2 << ...;
   os << collB.ptrToIndex( obj.ptrB );
}
 

Эту функцию можно зафрендить с классом А, что бы она имела доступ к закрытым членам.

UPDATE. Я кажется сообразил, что вы хотите посмотреть. Улыбающийся
При чтении индекс объекта я бы помещал в отдельный контейнер, т.е. указатель в объекте занулили, индекс сохранили во внешней коллекции.
Сразу после завершения процесса чтения, коллекция с индексами разрушиться и все про них забудут. А главное, в рабочих классах не будет никаких "технологических отверстий". Улыбающийся
« Последнее редактирование: Февраль 12, 2013, 18:08 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Февраль 13, 2013, 13:25 »

Код
C++ (Qt)
void saveObjectA( ostream &os, const A &obj, const Coll<B*> collB )
 
А откуда предположение что нужна именно Coll<B*>? Класс A может ссылаться на объекты любого типа, возможно и базового, поэтому делать общий доступ ко всем коллекциям сериализации придется, напр
Код
C++ (Qt)
template <class T>
const Coll<T *> & GetCollOfType( const T & );
 

UPDATE. Я кажется сообразил, что вы хотите посмотреть. Улыбающийся
При чтении индекс объекта я бы помещал в отдельный контейнер, т.е. указатель в объекте занулили, индекс сохранили во внешней коллекции.
Из этого неясно как же Вы собирались реализовать чтение. Ну получили контейнер индексов, как потом их присобачить к объектам на фазе resolve?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Февраль 13, 2013, 13:43 »

А откуда предположение что нужна именно Coll<B*>? Класс A может ссылаться на объекты любого типа, возможно и базового, поэтому делать общий доступ ко всем коллекциям сериализации придется, напр
Пожалуйста. Как вам будет удобней. Улыбающийся

Из этого неясно как же Вы собирались реализовать чтение. Ну получили контейнер индексов, как потом их присобачить к объектам на фазе resolve?
Ну примитивная же задача. Не придумаете, я вечером выложу код с комментариями. Сейчас не могу, убегаю.

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Февраль 13, 2013, 13:46 »

Ну примитивная же задача. Не придумаете, я вечером выложу код с комментариями. Сейчас не могу, убегаю.
Конечно, не горит. А как у меня сделано я уже показал (доп поле данных)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #12 : Февраль 13, 2013, 16:49 »

А как у меня сделано я уже показал (доп поле данных)

Внимание!!! Это просто набросок! Улыбающийся

Пытаемся избавится от доп полей, для этого используем коллекцию для сохранения индексов объектов.
Код
C++ (Qt)
// Функция верхнего уровня для загрузки данных
bool loadFile( ... )
{
   ifstream is;
   ...
   int version;
   is >> version;
 
   int numObjA;
   is >> numObjA;
 
   std::deque<ClassA *> collA( numObjA );
   std::deque<int> idxCollA( numObjA );
 
   for( int i = 0; i < numObjA; ++i )
   {
       int idx;
       ClassA *o = new ClassA;
       readObjectA( is, o, idx );
       collA[ i ] = o;
       idxCollA[ i ] = idx;
   }
 
   int numObjB;
   is >> numObjB;
 
   std::deque<ClassB *> collB( numObjB );
 
   for( int i = 0; i < numObjB; ++i )
   {
       ClassB *o = new ClassB;
       readObjectB( is, o, collA );    // Здесь мы уже можем резолвить указатели на объекты из контейнера А
       collA[ i ] = o;
   }
 
   // Резолвим индексы объектов из контейнера А.
   for( int i = 0; i < numObjA; ++i )
   {
       collA[ i ]->ptrB = collB[ idxCollA[ i ] ];
   }
}
 
void readObjectA( istream &is, A &obj, int &idx )
{
   is >> obj.data1 >> obj.data2 >> ...;
   is >> idx;  // Читаем индекс объекта для связи в контейнере B.
}
 

Писал прямо здесь.
Для коллекций не поддерживающих последовательный доступ пример переделывается элементарно.
« Последнее редактирование: Февраль 13, 2013, 16:53 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Февраль 13, 2013, 17:26 »

Внимание!!! Это просто набросок! Улыбающийся
Ладно, "на взлете бить не буду" Улыбающийся По существу: а почему Вы исходите из предположения что только класс A ссылается только на класс B и имеет строго 1 ссылку (указатель)?  Не наивно ли такое проектирование?  Улыбающийся

[/offtop]
На форуме много молодых людей которые много, ну очень много, знают. Более того, они стремятся знать все больше и больше. Ну у каждого свой подход. Я не стремлюсь знать больше, но мне интересно "как сделать конструкцию лучше", я люблю в этом копаться. Если Вам нет - я не хочу тратить Ваше время
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #14 : Февраль 13, 2013, 17:41 »

Ладно, "на взлете бить не буду" Улыбающийся
Конечно не будете. Бить то нечем. Если вы перечитаете всю тему и посмотрите "свои наброски" с mIndex, то поймете, что у вас точно такойже функционал, только с большими ограничениями. Улыбающийся
Вы предлагаете условия, а мы по ним играем... Не так ли?

но мне интересно "как сделать конструкцию лучше", я люблю в этом копаться. Если Вам нет - я не хочу тратить Ваше время
Не похоже. Улыбающийся
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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