Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Удаление класса в потоке 
:(
    Опции темы
Perovskit
Дата 30.7.2008, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 30.7.2008

Репутация: нет
Всего: нет



Добрый день


Я немного запутался в потоках. Пожалуйста, развейте сомнения.
Имеем класс:
class X {
private:
  //...
  bool valid;
public: 
  void Close();
  bool IsValid() { return valid; }
};
void X::Close() {
  valid = false;
}

Имеется два потока. В первом есть такое:
std::vector <X*> clients;
И он крутится в цикле с таймаутом 200мс.

А в другом -- работа с клиентами. Периодически вызываются разные функции.
Но вот, какой-то клиент потерял смысл(не валидный):
2-й поток:
clients[i]->Close();

На каждой итерации первый поток ищет невалидных клиентов и удаляет их:
for(;;) {
   delay(200);
   //...
   if(!clients[i].IsValid()) {
     delete clients[i];
     удаляем указатель из вектора
   }
}
Вопрос: возможно ли, что сразу после выполнения valid = false во втором потоке управление передастся в первый поток, где IsValid == false и будет вызвано delete clients[i] в то время, когда второй поток так и не вышел из функции-члена этого класса? Получится так, что первый поток удалил класс, хотя в нем еще находился второй поток. Это верно? И как с этим бороться (если надо)?
PM MAIL   Вверх
Alexeis
Дата 31.7.2008, 10:07 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: нет
Всего: 459



Цитата(Perovskit @  30.7.2008,  22:34 Найти цитируемый пост)
Вопрос: возможно ли, что сразу после выполнения valid = false во втором потоке управление передастся в первый поток, где IsValid == false и будет вызвано delete clients[i] в то время, когда второй поток так и не вышел из функции-члена этого класса? Получится так, что первый поток удалил класс, хотя в нем еще находился второй поток. Это верно? И как с этим бороться (если надо)? 

  Вполне возможно, но в этом нет ничего страшного. Функция класса почти ничем не отличается от простой функции. Важно чтобы после выполнения valid = false; не производилось обращение к другим полям объекта. А так ничем не грозит.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Perovskit
Дата 31.7.2008, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 30.7.2008

Репутация: нет
Всего: нет



все ясно. Благодарю.
PM MAIL   Вверх
Lazin
Дата 31.7.2008, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 1
Всего: 154



нужно синхронизировать доступ к вектору, если другие потоки читают из вектора, то из него ничего нельзя удалять, и наоборот, если один из потоков удаляет элементы из вектора, ни один другой поток не должен иметь возможность читать из него данные, так как может произойти reallok буфера вектора и у другого потока окажется невалидный итератор...
самый простой вариант - использовать мьютекс... перед тем как обратиться к данным вектора поток должен его захватить, а после этого - освободить, более оптимальным будет использование Read-Write блокировок (в случае если несколько потоков могут одновременно, безопасно читать данные, это соблюдается для STL контейнеров, но может не соблюдаться для твоих классов)... 
еще более оптимальным было-бы использование более удобных для многопоточной обработки структур данных, которые можно изменять из разных потоков одновременно..
зы
используй тэги [code]
PM MAIL Skype GTalk   Вверх
Alexeis
Дата 31.7.2008, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: нет
Всего: 459



Lazin, это уже другой вопрос. Читай внимательно 
Цитата(Perovskit @  30.7.2008,  22:34 Найти цитируемый пост)
где IsValid == false и будет вызвано delete clients[i] в то время, когда второй поток так и не вышел из функции-члена этого класса?

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


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Perovskit
Дата 31.7.2008, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 30.7.2008

Репутация: нет
Всего: нет



Lazin все верно, но все экземпляры класса X конструктором регистрируются в отдельном статическом векторе и обслуживаются вторым потоком. По сути, код первого и второго потоков совершенно независим. Там-то естественно мьютексами защищаются данные от одновременного доступа и когда класс теряет смысл, он безопасно удаляется из статического вектора и поднимается флажок valid = false. Да, это не очень приятно, т.к. вообще говоря, корректность зависит от явного положения valid=false именно в конце ритуала по невалидности клиента. 

Можно в деструктор клиента засунуть захват мьютекса, но пока не понял, где его еще захватить чтобы гарантировать, что после удаления не будет обращений к внутренним членам класса.
PM MAIL   Вверх
Lazin
Дата 31.7.2008, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 1
Всего: 154



Цитата(Alexeis @  31.7.2008,  11:01 Найти цитируемый пост)
То что поток находиться в функции объекта никак не мешает его удалению, если в функции нет обращений к полям класса. То что обращение к общим данным требует синхронизации очевидно, я говорил о том что завершение функции объекта не приводит к обращению к его полям. 

так и есть

Добавлено через 3 минуты и 55 секунд
может использовать подсчет ссылок?
например boost::shared_ptr, в этом случае объект будет удален только после того как программа не может к нему обратиться (так как ссылок на него больше нет)
в этом случае нужно будет просто удалить объект из контейнера...
PM MAIL Skype GTalk   Вверх
Perovskit
Дата 31.7.2008, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 30.7.2008

Репутация: нет
Всего: нет



Да, не подумал. 

Хорошая идея, спасибо. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0510 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.