Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема ИТ - проблемы с итераторами (число прочтений - 2840 )
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
ИТ - проблемы с итераторами
18. Декабря 2007 :: 11:26
Печать  
В рамках обдумывания идей реорганизации итераторов выяснилось, что и в текущей версии ИТ итераторы также весьма хрупкие.
Проблемы можно получить разными способами:

Код
Выбрать все
Процедура Сформировать1()
	_т =СоздатьОбъект("ИндексированнаяТаблица");
	_т.НоваяКолонка("Кол1");
	_т.НоваяСтрока(); _т.Кол1 =1;
	_т.НоваяСтрока(); _т.Кол1 =2;
	_т.НоваяСтрока(); _т.Кол1 =3;

	_т.ДобавитьИндекс("Кол1", "Кол1");

	_т.ВыбратьСтроки("Кол1");
	Пока _т.ПолучитьСтроку("Кол1") =1 Цикл
		Сообщить(_т.Кол1);
		_т.УдалитьСтроки();
	КонецЦикла;
КонецПроцедуры
 



Код
Выбрать все
Процедура Сформировать2()
	_т =СоздатьОбъект("ИндексированнаяТаблица");
	_т.НоваяКолонка("Кол1");
	_т.НоваяСтрока(); _т.Кол1 =1;
	_т.НоваяСтрока(); _т.Кол1 =2;
	_т.НоваяСтрока(); _т.Кол1 =3;

	_т.ДобавитьИндекс("Кол1", "Кол1");

	_т.ВыбратьСтроки("Кол1");
	Пока _т.ПолучитьСтроку("Кол1") =1 Цикл
		Сообщить(_т.Кол1);
		_т.УдалитьСтроку(1);
		Сообщить(_т.Кол1);
		Прервать;
	КонецЦикла;
КонецПроцедуры
 



и т.д.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: ИТ - проблемы с итераторами
Ответ #1 - 19. Декабря 2007 :: 05:22
Печать  
С первым вариантом всё ясно.  Просто забыл итераторы прибить.  Щас прибью Улыбка

Во втором случае надо немного видоизменить тест:
Код
Выбрать все
Процедура ПадениеИтератора2()
	_т =СоздатьОбъект("ИндексированнаяТаблица");
	_т.НоваяКолонка("Кол1");
	_т.НоваяСтрока(); _т.Кол1 =1;
	_т.НоваяСтрока(); _т.Кол1 =2;
	_т.НоваяСтрока(); _т.Кол1 =3;

	_т.ДобавитьИндекс("Кол1", "Кол1");

	_т.ВыбратьСтроки("Кол1");
	Пока _т.ПолучитьСтроку("Кол1") =1 Цикл
		Сообщить(""+_т.НомерСтроки("Кол1")+": Кол1 = "+_т.Кол1);
		_т.УдалитьСтроку(1);
		Сообщить(""+_т.НомерСтроки("Кол1")+": Кол1 = "+_т.Кол1+", "+_т.Получить(_т.НомерСтроки("Кол1"), "Кол1"));
		Прервать;
	КонецЦикла;
КонецПроцедуры
 


Только выполни его обязательно, поведение итератора всё равно косячное. По идее, если в дереве происходят какие-то изменения в процессе итерации, надо брать ключ, и искать строку по условию >=, учитывая при этом что индексы бывают неуникальными.  Сейчас же просто делается Next(), и как будто бы все счастливы... а счастья то как раз и нету...
Отработка выражений типа _т.Кол1 в текущей реализации ИТ врядли возможно, т.к. индексов может быть много.  Вот с выделенными итераторами это можно легко сделать.
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ИТ - проблемы с итераторами
Ответ #2 - 19. Декабря 2007 :: 17:11
Печать  
ADirks писал(а) 19. Декабря 2007 :: 05:22:
Код
Выбрать все
	_т.ВыбратьСтроки("Кол1");
	Пока _т.ПолучитьСтроку("Кол1") =1 Цикл
		Сообщить(""+_т.НомерСтроки("Кол1")+": Кол1 = "+_т.Кол1);
		_т.УдалитьСтроку(1);
		Сообщить(""+_т.НомерСтроки("Кол1")+": Кол1 = "+_т.Кол1+", "+_т.Получить(_т.НомерСтроки("Кол1"), "Кол1"));
		Прервать;
	КонецЦикла;
КонецПроцедуры
 


Только выполни его обязательно, поведение итератора всё равно косячное.


О. Познавательно. Улыбка
Без итераторов ситуация вырождается в такой вариант:
Код
Выбрать все
	Сообщить("Номер строки: " +_т.НомерСтроки +", значение: " +_т.Кол1);
	_т.НомерСтроки =1;
	Сообщить("Номер строки: " +_т.НомерСтроки +", значение: " +_т.Кол1);
	_т.УдалитьСтроку(1);
	Сообщить("Номер строки: " +_т.НомерСтроки +", значение: " +_т.Кол1);
 


Смысл в том, что текущая строка удалена, но ссылка в pCurrentRow остается.
Ну, здесь, конечно, решается легко, если я правильно понимаю.

Цитата:
Отработка выражений типа _т.Кол1 в текущей реализации ИТ врядли возможно, т.к. индексов может быть много.  Вот с выделенными итераторами это можно легко сделать.

Вот здесь чего-то мной не догоняется.
_т.Кол1 - это же уже не проблема итератора - это проблема зависшей ссылки на текущую строку (глобальную).
Или нет?

Цитата:
По идее, если в дереве происходят какие-то изменения в процессе итерации, надо брать ключ, и искать строку по условию >=, учитывая при этом что индексы бывают неуникальными.  Сейчас же просто делается Next(), и как будто бы все счастливы... а счастья то как раз и нету...

Леша, я вот к чему пока пришел.

Надо разделить 2 состояния индекса: состояние итерирования и состояние обновления.
Я бы предложил вообще при переходе в состояние обновления инвалидировать все итераторы по данному индексу.
Т.е. изменили индекс - нет проблем, но все итераторы будьте любезны найти заново (по ключам, или еще как - не важно).

Особенно это актуально как раз для отвязанных итераторов, где "щас прибью" сделать проблематичнее Улыбка

В качестве реализации я подумываю просто сделать поле "версии" индекса, инкрементируемое при любых операциях с индексом.
Итератор ссылается на индекс, с учетом поля "версии".
Как только версия итератора перестает соответствовать версии индекса, он инвалидируется.

Как такая схема? Ничего я не забыл?
  

De quelle planète es-tu?
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: ИТ - проблемы с итераторами
Ответ #3 - 20. Декабря 2007 :: 04:49
Печать  
Цитата:
Цитата:
Отработка выражений типа _т.Кол1 в текущей реализации ИТ врядли возможно, т.к. индексов может быть много.  Вот с выделенными итераторами это можно легко сделать.

Вот здесь чего-то мной не догоняется.
_т.Кол1 - это же уже не проблема итератора - это проблема зависшей ссылки на текущую строку (глобальную).
Или нет?

Ну да, проблема в том, что параллельно существующих иераторов может быть много, а ТекущаяСтрока - одна на всю таблицу, что порождает непонятки при кодировании, и легко приводит к труднообнаружимым ошибкам. Вот если бы писать
Код
Выбрать все
_ит = _т.СоздатьИтератор("Кол1");
_ит.Вперед();
_ит.СледующаяСтрока();
Сообщить(_ит.Кол1); 


то всё будет прозрачно

Цитата:
Надо разделить 2 состояния индекса: состояние итерирования и состояние обновления.
Я бы предложил вообще при переходе в состояние обновления инвалидировать все итераторы по данному индексу.
Т.е. изменили индекс - нет проблем, но все итераторы будьте любезны найти заново (по ключам, или еще как - не важно).

Видимо да. К чёрту всякие исхищрения. Сломали индекс - будте любезны обновить итераторы.  Простые решения - они всегда самые надёжные  Улыбка

Цитата:
В качестве реализации я подумываю просто сделать поле "версии" индекса, инкрементируемое при любых операциях с индексом.
Итератор ссылается на индекс, с учетом поля "версии".
Как только версия итератора перестает соответствовать версии индекса, он инвалидируется.

Как такая схема? Ничего я не забыл?

Ага, нормальная схема.
  
Наверх
 
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ИТ - проблемы с итераторами
Ответ #4 - 20. Декабря 2007 :: 04:55
Печать  
1. Алексей, а почему бы не сделать подобные выделенные итераторы? Проблемы с реализацией, совместимостью или еще чем?
2. Каким образом пользователь узнает о том, что итератор перестал быть валидным?
ИМХО нужно как-то так: обновили индекс, обратились к итератору или выполнили движение по таблице, получили исключение Улыбка
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer && tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: ИТ - проблемы с итераторами
Ответ #5 - 20. Декабря 2007 :: 07:01
Печать  
Цитата:
1. Алексей, а почему бы не сделать подобные выделенные итераторы? Проблемы с реализацией, совместимостью или еще чем?

Да я просто не знаю, как это делать. Чисто технически.  Я понимаю, что это несложно, но ведь надо разбираться, а времени нет как всегда  Печаль

Цитата:
2. Каким образом пользователь узнает о том, что итератор перестал быть валидным?
ИМХО нужно как-то так: обновили индекс, обратились к итератору или выполнили движение по таблице, получили исключение Улыбка

Как обычно, в итераторах существует метод IsValid(). Ну и если кто-то попытается дёргать инвалидный итератор, то получит исключение.
  
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: ИТ - проблемы с итераторами
Ответ #6 - 20. Декабря 2007 :: 10:21
Печать  
Блин, щас посмотрел в реализацию получения/установления значения в текущей строке, там же фигня какая-то.  Если текущей строки нет, то тихонько ничего не делается и всё.  А надо же ведь исключение выкидывать, а?
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ИТ - проблемы с итераторами
Ответ #7 - 20. Декабря 2007 :: 10:47
Печать  
Я поэтому в багзилле так смутно цели исследования записал Улыбка
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: ИТ - проблемы с итераторами
Ответ #8 - 20. Декабря 2007 :: 14:00
Печать  
kms писал(а) 19. Декабря 2007 :: 17:11:
В качестве реализации я подумываю просто сделать поле "версии" индекса, инкрементируемое при любых операциях с индексом.
Итератор ссылается на индекс, с учетом поля "версии".
Как только версия итератора перестает соответствовать версии индекса, он инвалидируется.

Как такая схема? Ничего я не забыл?

Может быть, лучше использовать механизм подписки на события? Итератор подписывается на событие "изменение данных". При получении события выставляет флаг инвалидности. При установленном флаге на все попытки использования итератора выкидывает ошибку или как-то обновляет свои данные. Мне кажется, выглядит как-то симпатичнее. Да и такой механизм может применяться не только для обработки ошибок с итераторами. Например, ИТ отображается в ТП. Кто-то меняет данные в ИТ. Срабатывает событие, которое при обработке провайдером приводит к обновлению ТП.

Для реализации можно либо использовать какой-нибудь интерфейс типа ISubscriber, либо boost::function.
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ИТ - проблемы с итераторами
Ответ #9 - 20. Декабря 2007 :: 15:05
Печать  
Uzhast писал(а) 20. Декабря 2007 :: 14:00:
Может быть, лучше использовать механизм подписки на события? Итератор подписывается на событие "изменение данных". При получении события выставляет флаг инвалидности. При установленном флаге на все попытки использования итератора выкидывает ошибку или как-то обновляет свои данные. Мне кажется, выглядит как-то симпатичнее. Да и такой механизм может применяться не только для обработки ошибок с итераторами. Например, ИТ отображается в ТП. Кто-то меняет данные в ИТ. Срабатывает событие, которое при обработке провайдером приводит к обновлению ТП.

Для реализации можно либо использовать какой-нибудь интерфейс типа ISubscriber, либо boost::function.

О. тоже вариант; но получится посложнее.

Отличается, кстати, по точке потерь: в варианте с событиями потери на оповещение идут при операциях над индексами (время пропорционально числу зависимых итераторов), а в варианте с проверкой - при операциях над итераторами (время const).
Хотя если не размножать итераторы миллионами, потери эти роли не играют.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать