Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
#1

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

13.06.2014, 14:43. Просмотров 729. Ответов 24
Метки нет (Все метки)

Сам вопрос возник, когда работал с 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
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.06.2014, 14:43
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как удалить объект, который это попросил? (C++):

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

this это адресс объекта, а *this это сам объект. я всё правельно понял? - C++
this это адресс объекта, а *this это сам объект. я всё правельно понял?

Как удалить базовый объект? - C++
Пишу под symbian, здесь Mbase вроде интерфейсов C#: class Mbase { virtual void foo1()=0; virtual void foo2()=0; virtual ...

Как удалить объект через указатель? - C++
Делаю консольный тетрис. Задаю указатель на объект класса Block. В if создаю объект класса, а потом этот объект нужно удалить. как удалить...

Как удалить объект списка list? - C++
у меня есть pPlan - это указатель на класс Plan. Listabit - список, созданный в классе Plan . pPlan-&gt;Listabit;// вот я на него ссылаюсь ...

Как удалить объект по указателю на базовый класс? - C++
Допустим есть несколько классов: // абстрактный класс - введен для управления наследниками class A{ ... } // рабочий класс...

24
Kuzia domovenok
1951 / 1804 / 140
Регистрация: 25.03.2012
Сообщений: 6,247
Записей в блоге: 1
13.06.2014, 14:55 #2
Condition variable тебе поможет?
1
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 15:15  [ТС] #3
Kuzia domovenok, не сталкивался. Насколько я понял, для его работы необходим мьютекс? Если я прав, то хотелось бы найти решение получше, ибо создавать на каждый объект по мьютексу (а он, вроде как, объект ядра, коих и так мало), когда этих объектов может быть туча - не есть хорошо.
0
Jupiter
Каратель
Эксперт С++
6559 / 3980 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
13.06.2014, 17:30 #4
Цитата Сообщение от nexen Посмотреть сообщение
(а он, вроде как, объект ядра, коих и так мало
std::mutex не предназначен для синхронизации процессов и потому глупо в его реализации под Windows использовать мьютекс как объект ядра, скорее всего реализация основана на критических секциях
1
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 17:39  [ТС] #5
Jupiter, поподробнее О_о Как не предназначен для синхронизации? Вы мне шаблон ломаете
0
Jupiter
Каратель
Эксперт С++
6559 / 3980 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
13.06.2014, 17:40 #6
nexen,
Цитата Сообщение от Jupiter Посмотреть сообщение
не предназначен для синхронизации процессов
...
1
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 17:41  [ТС] #7

Не по теме:

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


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

Не по теме:

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

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



Добавлено через 10 минут
Цитата Сообщение от nexen Посмотреть сообщение
Вы тоже считаете, что с моей проблемой лучше использовать variable condition?
по приведенному коду трудно оценить проблему, не вижу смысла в поле класса A* a, его спокойно можно создавать локально в методе run и затем параметром передавать в downloadFinished где и спокойно удалять
1
Renji
1969 / 1367 / 308
Регистрация: 05.06.2014
Сообщений: 3,898
13.06.2014, 18:10 #9
Как удалить объект А, созданный в другом потоке, который завершил свое исполнение?
Пожалуйста, с этого места по подробнее:
C++
1
a->download(); // Так же создает ещё один поток для метода download();
Что дальше происходит?
1) Основной поток крутится дальше, не дожидаясь завершения a->download(). Где вы тогда результаты a->download() получаете?
2) Основной поток ждет завершения a->download(). Какая тогда к Ктулху разница один поток у вас или два?
0
Trwsdf
Заблокирован
13.06.2014, 18:10 #10
Цитата Сообщение от nexen Посмотреть сообщение
Как удалить объект А, созданный в другом потоке, который завершил свое исполнение?
C++
1
std::unique_ptr, shared_ptr,weak_ptr
Поток который завершает работу и оставляет мусор после себя. Либо поток ждет пока все окончится, либо удаляет мусор перед завершением, не додумался до этого? Так додумайся, иначе тому кто будет сопровождать код не позавидуешь.
0
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. Вариант - оставить А и указать в О ссылку на данные в А - не подходит)
0
Renji
1969 / 1367 / 308
Регистрация: 05.06.2014
Сообщений: 3,898
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;
    }
0
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 19:24  [ТС] #13
Renji,
тем, что
C++
1
delete this;
0
Kuzia domovenok
1951 / 1804 / 140
Регистрация: 25.03.2012
Сообщений: 6,247
Записей в блоге: 1
13.06.2014, 19:42 #14
И что не так?
0
Renji
1969 / 1367 / 308
Регистрация: 05.06.2014
Сообщений: 3,898
13.06.2014, 19:45 #15
тем, что
Окей. Пишем вместо этого
C++
1
2
3
crap_mutex.lock();
crap.push_back(this);
crap_mutex.unlock();
После unlock, но до того как завершится функция download (ну вот совпало так) приходит сборщик мусора и выполняет ровно тот же delete. Что-то принципиально изменилось?
0
13.06.2014, 19:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.06.2014, 19:45
Привет! Вот еще темы с ответами:

Нужно удалить слова как это сделать? - C++
Есть такой текст &quot;for do while int void using while&quot; нужно удалить слова &quot;while&quot; как это сделать?

Как удалить символ перевода строки, который оставляет cin - C++
Как удалить символ перевода строки, который оставляет cin. Нужно вводить в строчку чаровые переменные, и чтобы они так в строке и...

Как удалить каталог, который имеет вложеные папки и файлы? - C++
С помощью каких средств это можно реализовать? Есть функция _rmdir(const char*) в direct.h, но она удаляет только пустой каталог. Я...

Не получается удалить минимальный элемент в массиве и вывести новый. Как сделать это? - C++
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;locale&gt; using namespace std; int main() { setlocale( LC_ALL,&quot;Russian&quot; ); ...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru