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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> локальный сборщик мусора 
:(
    Опции темы
Леопольд
Дата 30.6.2009, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Lazin @ 30.6.2009,  05:51)
Цитата(ЗапаснойЛеопольд @  29.6.2009,  22:58 Найти цитируемый пост)
Не понял. Чем это удобнее чем man.push<garbage::del_array>(new int[10])?   Буду благодарен за пример...

ты же попросил пример smile 

Я имел ввиду пример использования. smile

Т.е., допустим, есть жалоба от потенциального пользователя что использование моей штуковины неудобное.

Я не знаю как можно придумать удобнее, сохранив при этом обобщённость:
============================================================================================
garbage::collector cleaner;

...
AnyType* ptr = cleaner.push<garbage::del_single>(new AnyType);
...
AnotherType* array = cleaner.push<garbage::del_array>(new AnotherType[size]);
...
SpecialType* something = cleaner.push<special_clean_array>(special_alloc(SpecialType));
============================================================================================
Если есть идеи, как можно упростить это или сделать более наглядным, буду благодарен... smile

Добавлено @ 22:55
Цитата(Lazin @ 30.6.2009,  05:51)
можно еще использовать идиому traits
...
в этом случае тебе не нужно будет явно указывать garbage::del_array для каждого вызова, вместо этого ты можешь специализировать класс del_traits, для своего типа, и он будет использоваться в методе push

traits не подходит по той причине что я могу захотеть удалять указатель на один и тот же тип разными способами.

Т.е.
int* ptr = cleaner.push<garbage::del_single>(new int);
int* array = cleaner.push<garbage::del_array>(new int[size]);

Добавлено @ 22:59
Я переписал утилитку, gcc не хотел собирать (новая версия в первом посте). Получилось даже лучше. Я так же изменил способ хранения указателей на объекты на максимально лёгкий, какой смог придумать. Теперь сборщик уступает scoped_array (для целей локальной автоуборки) только виртуальными вызовами деструкторов. Это плата за универсальность. Хотя, было бы неплохо от этого избавиться. Но как это сделать не меняя способа использования, я не знаю.

Это сообщение отредактировал(а) Леопольд - 30.6.2009, 23:03


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Леопольд
Дата 30.6.2009, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(DrHex @ 30.6.2009,  00:53)
Зачем вообще collector? Деструктор не годится?(collector только добовляет накладные ресурсы)

Можно поподробнее? Ничего же не понятно...


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 1.7.2009, 01:32 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



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



--------------------
PM MAIL WWW   Вверх
Lazin
Дата 1.7.2009, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Леопольд @  30.6.2009,  22:49 Найти цитируемый пост)
Я не знаю как можно придумать удобнее, сохранив при этом обобщённость

так у тебя там и нет особой обобщенности, все довольно жестко задается на этапе компиляции...
например, у меня есть класс - пулл объектов, в котором я выделяю память, допустим, для удаления объекта, нужно вызывать метод free пулла, и передать в него указатель на объект, который нужно удалить.. допустим, в программе может быть несколько таких пуллов
в этом случае, твой deleter должен получать ссылку или указатель на пул объектов, из которого нужно этот объект потом удалить, с твоим кодом это сделать не получится, следовательно он не гибок smile 

Цитата(Леопольд @  30.6.2009,  22:49 Найти цитируемый пост)
Если есть идеи, как можно упростить это или сделать более наглядным, буду благодарен...
во первых, ты объединяешь множество не связанных операций в одну операцию, это уже не правильно
во вторых, у тебя объекты могут удалятся в произвольном порядке, это зависит от того, как их добавлять, если порядок удаления важен, то это может вызвать сложности

Цитата(Леопольд @  30.6.2009,  22:49 Найти цитируемый пост)
traits не подходит по той причине что я могу захотеть удалять указатель на один и тот же тип разными способами.

Т.е.
int* ptr = cleaner.push<garbage::del_single>(new int);
int* array = cleaner.push<garbage::del_array>(new int[size]);

это уже извращение, для массивов есть vector smile 
к тому-же, если у тебя объект одного типа удаляется несколькими разными способами, то это уже ошибка, лучше всего делать так, что-бы можно было на этапе компиляции однозначно определить как удалять объект, к примеру, если у тебя есть класс Foo, и он может быть создан в куче или с помощью специализированного менеджера памяти(и удаляться с помощью него), то во втором случае, лучше использовать какой-нибудь смарт поинтер вместо обычного указателя, что-бы можно было определить на этапе компиляции, как удалять объект. smile 
я сделал-бы это так:
Код

template<class T>
struct scoped_delete_base
{
    virtual void operator ()(T* t) = 0;
};

template<class T>
struct scoped_ptr_impl : scoped_delete_base<T>
{
    void operator ()(T* t)
    {
        delete t;
    }
};

template<class T>
struct scoped_array_impl : scoped_delete_base<T>
{
    void operator ()(T* t)
    {
        delete [] t;
    }
};

template<class T, class F>
struct scoped_func_impl : scoped_delete_base<T>
{
    F f;
    scoped_func_impl(F f)
        : f(f)
    {
    }
    
    void operator ()(T* t)
    {
        f(t);
    }
};

template<class T>
class scoped_ptr
{
    T* ptr_;
    scoped_delete_base<T>* impl_;
public:
    scoped_ptr(T* t)
        : ptr_(t)
        , impl_(new scoped_ptr_impl<T>()) //обычное удаление
    {
    }

    template<class F>
    scoped_ptr(T* t, F f)
        : ptr_(t)
        , impl_(new scoped_func_impl<T, F>(f))//удаление с помощью функтора
    {
    }
    
    ~scoped_ptr()
    {
        (*impl_)(ptr_);
        delete impl_;
    }
};

template<class T>
class scoped_array
{

    T* ptr_;
    scoped_delete_base<T>* impl_;
public:
    scoped_array(T* t)
        : ptr_(t)
        , impl_(new scoped_array_impl<T>()) //обычное удаление
    {
    }

    template<class F>
    scoped_array(T* t, F f)
        : ptr_(t)
        , impl_(new scoped_func_impl<T, F>(f))//удаление с помощью функтора
    {
    }
    
    ~scoped_array()
    {
        (*impl_)(ptr_);
        delete [] impl_;
    }
};

ничего не напоминает? smile 

Это сообщение отредактировал(а) Lazin - 1.7.2009, 08:50
PM MAIL Skype GTalk   Вверх
ЗапаснойЛеопольд
Дата 1.7.2009, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Lazin @ 1.7.2009,  08:42)
Цитата(Леопольд @  30.6.2009,  22:49 Найти цитируемый пост)
Если есть идеи, как можно упростить это или сделать более наглядным, буду благодарен...
во первых, ты объединяешь множество не связанных операций в одну операцию, это уже не правильно
во вторых, у тебя объекты могут удалятся в произвольном порядке, это зависит от того, как их добавлять, если порядок удаления важен, то это может вызвать сложности

каких именно несвязанных операций и почему они несвязанные?
объекты удаляются в порядке обратном созданию.
PM MAIL   Вверх
Леопольд
Дата 1.7.2009, 09:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Lazin @ 1.7.2009,  08:42)
Цитата(Леопольд @  30.6.2009,  22:49 Найти цитируемый пост)
traits не подходит по той причине что я могу захотеть удалять указатель на один и тот же тип разными способами.

Т.е.
int* ptr = cleaner.push<garbage::del_single>(new int);
int* array = cleaner.push<garbage::del_array>(new int[size]);

это уже извращение, для массивов есть vector smile 

Вот ещё одно извращение smile
Код

int* ptri = cleaner.push<garbage::free_c>((int*)malloc(sizeof(int)));


Добавлено через 1 минуту и 56 секунд
Цитата(Lazin @ 1.7.2009,  08:42)
Цитата(Леопольд @  30.6.2009,  22:49 Найти цитируемый пост)
Я не знаю как можно придумать удобнее, сохранив при этом обобщённость

так у тебя там и нет особой обобщенности, все довольно жестко задается на этапе компиляции...
например, у меня есть класс - пулл объектов, в котором я выделяю память, допустим, для удаления объекта, нужно вызывать метод free пулла, и передать в него указатель на объект, который нужно удалить.. допустим, в программе может быть несколько таких пуллов
в этом случае, твой deleter должен получать ссылку или указатель на пул объектов, из которого нужно этот объект потом удалить, с твоим кодом это сделать не получится, следовательно он не гибок smile

Напиши пожалуйста интерфейс пула, а я попытаюсь им воспользоваться...

Это сообщение отредактировал(а) Леопольд - 1.7.2009, 09:17


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Lazin
Дата 1.7.2009, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



они удаляются в порядке, обратном вызовам ф-ии push smile 
если у меня есть объекты А и Б и я хочу, что-бы они были удалены после выхода из scope, то зачем-то создается список, в котором лежат указатели на А и Б(это как минимум два выделения памяти в куче), хотя достаточно пары стековых объектов?
почему удаление объектов А и Б должно для меня выглядеть как одна операция, хотя это 2 операции не связанные между собой? smile

Добавлено через 5 минут и 10 секунд
Цитата(Леопольд @  1.7.2009,  09:16 Найти цитируемый пост)
Напиши пожалуйста интерфейс пула, а я попытаюсь им воспользоваться...


Код

template<class T>
class ObjectPool
{
public:
    T* create();
    void free(T* p);
};


создание
Код

ObjectPool<Foo> pool;

Foo* f = pool.create();


удаление

Код

pool.free(f);


Код

collector.push<WTF?? адрес pool не известен на этапе компиляции!!>(f);

PM MAIL Skype GTalk   Вверх
Леопольд
Дата 1.7.2009, 09:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Lazin @ 1.7.2009,  08:42)
к тому-же, если у тебя объект одного типа удаляется несколькими разными способами, то это уже ошибка, лучше всего делать так, что-бы можно было на этапе компиляции однозначно определить как удалять объект

Т.е. получается что С++ изначально имеет изъян, потому что позволят это делать... smile Почему ты считаешь что между типом объекта и способом выделения и освобождения памяти должна быть настолько жёсткая связь? Если это идиома, или code rule, то объясни, пожалуйста, её выгоды.


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Lazin
Дата 1.7.2009, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Леопольд @  1.7.2009,  09:28 Найти цитируемый пост)
Почему ты считаешь что между типом объекта и способом выделения и освобождения памяти должна быть настолько жёсткая связь?

А разве это не так? Если у тебя объект Foo* можно удалить 2мя способами, то как черт возьми я могу понять, глядя на этот указатель, как мне его удалить, не проследив его жизненный путь до момента создания? Ты хотел-бы разбираться потом в таком коде? Я - нет.
PM MAIL Skype GTalk   Вверх
mes
Дата 1.7.2009, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата
к тому-же, если у тебя объект одного типа удаляется несколькими разными способами, то это уже ошибка, лучше всего делать так, что-бы можно было на этапе компиляции однозначно определить как удалять объект

не согласен

Цитата(Lazin @  1.7.2009,  08:38 Найти цитируемый пост)
Если у тебя объект Foo* можно удалить 2мя способами, то как черт возьми я могу понять, глядя на этот указатель, как мне его удалить, не проследив его жизненный путь до момента создания?

Лучше предъявить требование, чтоб создание  и удаление были в "пределах видимости" программиста, что в принципе соблюдается у Леопольда:
Цитата(Леопольд @  1.7.2009,  08:16 Найти цитируемый пост)
 cleaner.push<garbage::free_c>((int*)malloc(sizeof(int)));

операция удаления "выбрана" рядом с операцией создания.


Леопольд, но все же зачем
Цитата(mes @  1.7.2009,  00:32 Найти цитируемый пост)
нужен такой контейнер, да еще и локальный?
не проще ли было бы просто пользoвать обертку для каждого объекта отдельно ?

тоесть вместо garbage_container ипользовать garbage_object.

Это сообщение отредактировал(а) mes - 1.7.2009, 10:07


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


Эксперт
****


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

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



Цитата(mes @  1.7.2009,  10:07 Найти цитируемый пост)
операция удаления "выбрана" рядом с операцией создания.

никто не мешает мне передать в метод push что угодно smile 
Цитата(mes @  1.7.2009,  10:07 Найти цитируемый пост)
не согласен

мотивируй
PM MAIL Skype GTalk   Вверх
mes
Дата 1.7.2009, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(Lazin @  1.7.2009,  09:19 Найти цитируемый пост)
никто не мешает мне передать в метод push что угодно smile 

с этим согласен, но это решается путем объеденения создания/удаления в один аллокатор.
и если избавиться от контейнера, то интерфейс создания объекта будет такой
Код

garbage_object<TObject, new_delete_alloc> object; 

где в принципе этот аллокатор можно поставить по умолчанию:
Код

garbage_object<TObject> object; 



Цитата(Lazin @  1.7.2009,  09:19 Найти цитируемый пост)

к тому-же, если у тебя объект одного типа удаляется несколькими разными способами, то это уже ошибка, лучше всего делать так, что-бы можно было на этапе компиляции однозначно определить как удалять объект
Цитата

не согласен

мотивируй 

Объекту не желательно знать о способе своего создания и хранения. Для этого есть врапперы (такие как умные указатели) которые задают нужную политику.





Это сообщение отредактировал(а) mes - 1.7.2009, 12:08


--------------------
PM MAIL WWW   Вверх
Lazin
Дата 1.7.2009, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mes @  1.7.2009,  12:07 Найти цитируемый пост)
Объекту не желательно знать о способе своего создания и хранения. Для этого есть врапперы (такие как умные указатели) которые задают нужную политику.


Цитата(Lazin @  1.7.2009,  08:42 Найти цитируемый пост)
лучше использовать какой-нибудь смарт поинтер вместо обычного указателя, что-бы можно было определить на этапе компиляции, как удалять объект


я именно об этом и говорил
PM MAIL Skype GTalk   Вверх
mes
Дата 1.7.2009, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(Lazin @  1.7.2009,  11:58 Найти цитируемый пост)
я именно об этом и говорил 

 smile 

Цитата(Леопольд @  1.7.2009,  08:28 Найти цитируемый пост)
Т.е. получается что С++ изначально имеет изъян, потому что позволят это делать... 

Cpp позволяет очень многое(и именно с этим связаны многие трудности с его освоением), но это не является изъяном.
Просто он (cpp) полагается на то, что свобода выражения превыше жестких рамок. 

Это сообщение отредактировал(а) mes - 1.7.2009, 13:38


--------------------
PM MAIL WWW   Вверх
Lazin
Дата 1.7.2009, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



кстати, стоит отметить, что сабж - вовсе не сборщик мусора smile 
PM MAIL Skype GTalk   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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