Форум программистов, компьютерный форум CyberForum.ru

Как удалить объект, который это попросил? - C++

Восстановить пароль Регистрация
 
 
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 14:43     Как удалить объект, который это попросил? #1
Сам вопрос возник, когда работал с Qt и их системой signal/slot. Проблема на С++ выглядела бы так:
Есть два объекта: А(асинхронный) и О(ожидающий).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct O
{
    A *a;
    int downloadsAmount;
    MainObject *parent;
    
    void run() // Этот метод запускается в отдельном потоке. После его окончания, поток завершается
    {
        a = new A(this);
        a->download(); // Так же создает ещё один поток для метода download();
    }
    
    void downloadFinished()
    {
        ++downloadsAmount;
        parent->data = a->data; // по некоторым причинам, Data не является указателем
        // После сохранения data в MainObject, поток А тоже завершится (на самом деле в методе download(O *parent), но не суть. Главное, что теперь копия данных в А осталась без именений - её никто не удалил. В идеале было бы сделать, как ниже :
        
        // delete a; // но так нельзя, ведь после этого метода поток вернется в методе структуры А. Да, там больше нет обращения к данным А, но всё равно - это неправильно. В моем случае, это ошибка.
    }
}
 
struct A
{
    Data d; // не указатель
    
    void download(O *parent)
    {
        /*скачиваем*/
        parent->downloadFinished();
    }
}
Как удалить объект А, созданный в другом потоке, который завершил свое исполнение? Единственное, что я придумал, это занести его в какой-то глобальный
C++
1
vector < BaseObject * > crap;
- и каждую итерацию чего-нибудь очищать этот вектор. Само собой для вектора понадобится мьютекс, иначе не thread-safe. Есть ли иное решение?
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
13.06.2014, 14:55     Как удалить объект, который это попросил? #2
Condition variable тебе поможет?
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 15:15  [ТС]     Как удалить объект, который это попросил? #3
Kuzia domovenok, не сталкивался. Насколько я понял, для его работы необходим мьютекс? Если я прав, то хотелось бы найти решение получше, ибо создавать на каждый объект по мьютексу (а он, вроде как, объект ядра, коих и так мало), когда этих объектов может быть туча - не есть хорошо.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
13.06.2014, 17:30     Как удалить объект, который это попросил? #4
Цитата Сообщение от nexen Посмотреть сообщение
(а он, вроде как, объект ядра, коих и так мало
std::mutex не предназначен для синхронизации процессов и потому глупо в его реализации под Windows использовать мьютекс как объект ядра, скорее всего реализация основана на критических секциях
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 17:39  [ТС]     Как удалить объект, который это попросил? #5
Jupiter, поподробнее О_о Как не предназначен для синхронизации? Вы мне шаблон ломаете
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
13.06.2014, 17:40     Как удалить объект, который это попросил? #6
nexen,
Цитата Сообщение от Jupiter Посмотреть сообщение
не предназначен для синхронизации процессов
...
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 17:41  [ТС]     Как удалить объект, который это попросил? #7

Не по теме:

Jupiter, стоп. Мьютексы же именованны? В чем тогда проблема в синхронизации между процессами? Или что бы вы тогда использовали при синхронизации процессов?


Вы тоже считаете, что с моей проблемой лучше использовать variable condition?
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
13.06.2014, 18:03     Как удалить объект, который это попросил? #8

Не по теме:

nexen, вы путаете процессы и потоки.

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



Добавлено через 10 минут
Цитата Сообщение от nexen Посмотреть сообщение
Вы тоже считаете, что с моей проблемой лучше использовать variable condition?
по приведенному коду трудно оценить проблему, не вижу смысла в поле класса A* a, его спокойно можно создавать локально в методе run и затем параметром передавать в downloadFinished где и спокойно удалять
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
13.06.2014, 18:10     Как удалить объект, который это попросил? #9
Как удалить объект А, созданный в другом потоке, который завершил свое исполнение?
Пожалуйста, с этого места по подробнее:
C++
1
a->download(); // Так же создает ещё один поток для метода download();
Что дальше происходит?
1) Основной поток крутится дальше, не дожидаясь завершения a->download(). Где вы тогда результаты a->download() получаете?
2) Основной поток ждет завершения a->download(). Какая тогда к Ктулху разница один поток у вас или два?
Trwsdf
Заблокирован
13.06.2014, 18:10     Как удалить объект, который это попросил? #10
Цитата Сообщение от nexen Посмотреть сообщение
Как удалить объект А, созданный в другом потоке, который завершил свое исполнение?
C++
1
std::unique_ptr, shared_ptr,weak_ptr
Поток который завершает работу и оставляет мусор после себя. Либо поток ждет пока все окончится, либо удаляет мусор перед завершением, не додумался до этого? Так додумайся, иначе тому кто будет сопровождать код не позавидуешь.
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 18:59  [ТС]     Как удалить объект, который это попросил? #11
Jupiter, если вы имеете ввиду, что std::mutex не именованный, в отличие от CreateMutex в WinAPI, тогда я вас неравильно понял. К сожалению, C11++ использовать нельзя :<

Не по теме:

А в С11 как мьютекс сделан? Через КАС?


К сожалению, в данном случае у меня ограничение в Qt на посылаемый сигнал - он без параметров. Это обязательно.
Более того, сделав 'a' локальным, я уничтожу a->data, да и поток, который сейчас исполняет a->download() тоже охренеет от уничтожения своего объекта. Я не прав?
Даже если я создам 'a' локально в объекте класса О (не в методе run()), выйдет, что я его и вовсе не смогу удалить до тех пор, пока не удаляю О, а ведь мне нужно освободить a->data от данных)

Renji, поток O завершается после этой строчки. Поток А скачивает, заносит данные в свою data, затем вызывает downloadFinished() класса О, где заносит данные data этого класса.

Trwsdf, та же проблема. Без разницы - создам я 'A a' локально в run() или в объекте О, или через unique_ptr. Данные, занимаемые 'a' по прежнему будут висеть в объекте О, который может жить ещё долго. Однако сам 'а' больше не нужен, ведь он уже скачал все данные и перенес их в O (они должны быть именно в O. Вариант - оставить А и указать в О ссылку на данные в А - не подходит)
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
13.06.2014, 19:11     Как удалить объект, который это попросил? #12
Renji, поток O завершается после этой строчки. Поток А скачивает, заносит данные в свою data, затем вызывает downloadFinished() класса О, где заносит данные data этого класса.
Чем тогда не устраивает такой вариант?
C++
1
2
3
4
5
6
7
    void download(O *parent)
    {
        /*скачиваем*/
        parent->downloadFinished();
        parent->a=0;
        delete this;
    }
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 19:24  [ТС]     Как удалить объект, который это попросил? #13
Renji,
тем, что
C++
1
delete this;
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
13.06.2014, 19:42     Как удалить объект, который это попросил? #14
И что не так?
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
13.06.2014, 19:45     Как удалить объект, который это попросил? #15
тем, что
Окей. Пишем вместо этого
C++
1
2
3
crap_mutex.lock();
crap.push_back(this);
crap_mutex.unlock();
После unlock, но до того как завершится функция download (ну вот совпало так) приходит сборщик мусора и выполняет ровно тот же delete. Что-то принципиально изменилось?
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 19:49  [ТС]     Как удалить объект, который это попросил? #16
Kuzia domovenok, нельзя удалять себя же.
Renji, в этом и проблема, что выходит, удаляется объект с методом, который ещё выполняется. равносительно
C++
1
 delete this
практически
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
13.06.2014, 19:55     Как удалить объект, который это попросил? #17
Цитата Сообщение от nexen Посмотреть сообщение
C++
1
a = new A(this);
В современном C++ следует такого избегать (если конечно не используется Qt-подход с иерархией вложенных объектов). Как уже упоминал Trwsdf, следует обернуть в подходящий тип "умного" указателя, а не изгаляться с delete this. Мне кажется std::shared_ptr будет тут самым правильным вариантом.
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
13.06.2014, 20:00     Как удалить объект, который это попросил? #18
Renji, в этом и проблема, что выходит, удаляется объект с методом, который ещё выполняется.
Ну тогда радикально:
C++
1
2
3
4
5
6
7
static void download(O *parent)
{
    Data d;//каждый download в отдельном потоке, каждый d в отдельном стеке, new не нужен
    /*скачиваем*/
    parent->downloadFinished(d);
    //static функция, объекта нет, а раз объекта нет, то и delete не нужен
}
Как мне кажется std::shared_ptr будет тут самым правильным вариантом.
shared_ptr тоже вызовет непонравившийся ТС delete, просто неявно.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
13.06.2014, 20:07     Как удалить объект, который это попросил? #19
Цитата Сообщение от Renji Посмотреть сообщение
shared_ptr тоже вызовет непонравившийся ТС delete, просто неявно.
ТС не понравился delete this, насколько я понял, а не delete как таковой. Отсутствие delete - утечка памяти.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.06.2014, 20:19     Как удалить объект, который это попросил?
Еще ссылки по теме:

Что значит константный указатель на объект, указатель на константный объект, и как это можно использовать? C++
Нужно удалить слова как это сделать? C++
C++ Как удалить объект списка list?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
13.06.2014, 20:19     Как удалить объект, который это попросил? #20
ТС не понравился delete this, насколько я понял, а не delete как таковой.
Как я понял, ТС нужно чтобы объект удалялся после завершения метода download, но не из метода download. Если поставить shared_ptr внутрь метода, он и объект прибьет внутри метода. Если поставить shared_ptr снаружи, он вообще ничего не прибьет. По крайней мере, в тот момент, когда это надо ТС.
Yandex
Объявления
13.06.2014, 20:19     Как удалить объект, который это попросил?
Ответ Создать тему
Опции темы

Текущее время: 00:53. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru