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

Поиск:

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


Опытный
**


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

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



Локальный сборщик мусора. Подчищает "хвосты" во время саморазрушения. Безопасен при исключениях. Покритикуйте пожалуйста, только без грубостей, я нежный... smile

30.06.2009. Переписал. Интерфейс немного изменился.
Код
#ifndef GARBAGECOLLECTOR
#define GARBAGECOLLECTOR

#include <new>
#include <cstdlib>

namespace garbage{

  class garbage{
  private:
    garbage *prev;
    garbage& operator=(const garbage&);
    garbage(const garbage&);
  public:
    void set_tail(garbage * const ptr){
      prev = ptr;
    }

    garbage(void){}
    virtual ~garbage(){ if(prev) delete prev;}
  };

  template<class T, class DelPolitic>
    class auto_delete: public garbage{
    private:
      auto_delete(const auto_delete&);
      auto_delete& operator=(const auto_delete&);
      T* pimpl;
    public:
      auto_delete(T* ptr):pimpl(ptr){
      }
      ~auto_delete(){
        DelPolitic::clear(pimpl);
      }
    };

  class del_single{
  public:
  template<class T>
    static void clear(T* ptr){
      delete ptr;
    }
  };
  class del_array{
  public:
  template<class T>
    static void clear(T* ptr){
      delete[] ptr;
    }
  };
  class free_c{
  public:
  template<class T>
    static void clear(T* ptr){
      free(ptr);
    }
  };

  class collector{
  private:
    collector(const collector&);
    collector& operator=(const collector&);
    garbage * head;
  public:
    collector(void):head(0){}
    template<class DelPolitic, class T>
      T* push(T* ptr) throw(std::bad_alloc){
        if(!ptr) throw std::bad_alloc();
        garbage *pushed = static_cast<garbage*>(new auto_delete<T,DelPolitic>(ptr));
        pushed->set_tail(head);
        head = pushed;
        return ptr;
      }
    ~collector(){
      if(head) delete head;
    }
  };

}//    end namespace garbage
#endif


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


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


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

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



Цитата(Леопольд @  29.6.2009,  20:12 Найти цитируемый пост)
я нежный...

тьфу!


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Леопольд
Дата 29.6.2009, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Пример использования:
Код

#include <iostream>
#include <cstdlib>
#include "garbage_collector.hpp"

class Class{
public:
    ~Class(){
        std::cout<<"Class has been destroyed"<<std::endl;
    }
};
struct Struct{
public:
    ~Struct(){
        std::cout<<"Struct has been destroyed"<<std::endl;
    }
};


class free_c{
public:
template<class T>
    static void clear(T* ptr){
        free(ptr);
        std::cout<<"free has been performed"<<std::endl;
    }
};
int main(int argc, char* argv[])
{
        garbage::collector man;
        Class* ptrC = man.push<garbage::del_single>(new Class);
        Struct* ptrS = man.push<garbage::del_array>(new Struct[4]);
        int* ptri = man.push<free_c>((int*)malloc(sizeof(int)));
}


Добавлено @ 20:18
Цитата(andrew_121 @ 29.6.2009,  20:13)
Цитата(Леопольд @  29.6.2009,  20:12 Найти цитируемый пост)
я нежный...

тьфу!

очень конструктивно...

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


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


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

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



Цитата(Леопольд @  29.6.2009,  20:18 Найти цитируемый пост)
очень конструктивно...

Прошу прощения. Это не о коде!
Это реакция о том, что я процитировал.
Опять же, прошу прощения за оффтоп.

Мое почтение!


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Леопольд
Дата 29.6.2009, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(andrew_121 @ 29.6.2009,  20:30)
...
Мое почтение!

Блаженно улыбаюсь smile


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


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

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



Цитата(Леопольд @  29.6.2009,  20:18 Найти цитируемый пост)

Код

int main(int argc, char* argv[]){    
  collector man;    
  man.push<del_single>(new TestClass1);   
   man.push<del_array>(new TestClass2[4]);
}

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



--------------------
PM MAIL   Вверх
Леопольд
Дата 29.6.2009, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(zim22 @ 29.6.2009,  20:38)
неудобно использовать. коллектор надо создавать. потом вызывать его метод. передавать аргументы в шаблон...
нельзя оформить это в виде шаблонной функции со статическим хранилищем?

Если не создавать, то как разрушать автоматически, например, при порождении исключения?

Это сообщение отредактировал(а) Леопольд - 29.6.2009, 20:53


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


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

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



Цитата(Леопольд @  29.6.2009,  20:49 Найти цитируемый пост)
Если не создавать, то как вызвать деструктор несозданного объекта?

никак. деструктор вызывается автоматически. хотя можно и явно его вызвать smile

вы хотели расширить auto_ptr, чтобы он мог корректно работать с массивами?
имхо, лучше отдельный класс написать тогда:
Код

template<typename T> class auto_array {
    T* res;
public:
    explicit auto_array(T* ptr) : res(ptr) {}
    ~auto_array() { if (res) delete[] res); }
    T* get() { return res; }
};

здесь Страуструп объясняет, почему не нужен auto_array
Цитата

A better solution is to use a vector

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

#include <stdexcept>
#include <iostream>

// тестовый класс для хранения в глобальном массиве объектов
class C { 
public:
  C()  { std::cout << "C\n"; }  
  void fcn() { }
  ~C() { std::cout << "~C\n"; }
};

namespace {
  const int max_num_of_objects = 100;
  void *object_list[max_num_of_objects] = {0}; // глобальное хранилище объектов
  static int object_count = 0;
}

// сохранить указатель на объект в хранилище
template <typename T>
T *store_array(T *ptr) {  
  object_list[object_count++] = ptr;
  return ptr;
}

// вызвать delete для указателя и удалить ссылку на него из хранилища
template <typename T>
void free_array(T *ptr) {
  for (int i = 0; i < max_num_of_objects; i++) {
    if (object_list[i] == ptr) {
      object_list[i] = 0;
      delete [] ptr;
    }
  }
}

// удалить все объекты, на которые есть указатели
void collect_garbage() {
  for (int i = 0; i < max_num_of_objects; i++) {
    if (object_list[i] != 0) {
      delete [] object_list[i]; // не работает :)
      object_list[i] = 0;
    }
  }
}

// тестовая функция
void fcn() {
  C *ptr = store_array(new C[3]);
  (ptr + 2)->fcn();
  throw std::exception("yo");
  free_array(ptr);
}
int _tmain(int argc, _TCHAR* argv[])
{    
  try {
    fcn();
  } catch (...) {
    collect_garbage();
  }
    return 0;
}


Это сообщение отредактировал(а) zim22 - 29.6.2009, 21:36


--------------------
PM MAIL   Вверх
ЗапаснойЛеопольд
Дата 29.6.2009, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(zim22 @ 29.6.2009,  20:55)
вы хотели расширить auto_ptr, чтобы он мог корректно работать с массивами?

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

пример:
Код

template<class T>
    class free_c{
    public:
        static void clear(T* ptr){
            free(ptr);
            std::cout<<"free has been performed"<<std::endl;
        }
    };
int main(int argc, char* argv[])
{
    garbage::collector man;
    man.push<garbage::del_single>(new Class);
    man.push<garbage::del_array>(new Struct[4]);
    man.push<free_c>((int*)malloc(sizeof(int)));
}



По какой-то причине я не могу постить под моим основным аккаунтом на форуме до завтрашнего вечера. Я что-то нарушил?


Это сообщение отредактировал(а) ЗапаснойЛеопольд - 29.6.2009, 22:39
PM MAIL   Вверх
ЗапаснойЛеопольд
Дата 29.6.2009, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(zim22 @ 29.6.2009,  20:38)
неудобно использовать....передавать аргументы в шаблон...

В шаблоне передается шаблон smile Я не знаю, как можно сделать удобнее не потеряв масштабируемость. Есть идеи?

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

Можно усовершенстовть так, чтобы контейнер тоже задавался в виде шаблонного параметра. У меня не получилось сделать с аргументом шаблона по умолчанию, STL контейнеры имеют свои шаблонные параметры по умолчанию, а я не помню как это побороть.
Код

    template<template<class T> class Container = std::list>
        class collector{
        private:
            typedef auto_delete<void,del_dummy> garbage;

            collector(const collector&);
            collector& operator=(const collector&);
            Container<garbage> collection;


Это сообщение отредактировал(а) ЗапаснойЛеопольд - 29.6.2009, 22:37
PM MAIL   Вверх
andrew_121
Дата 29.6.2009, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

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



ЗапаснойЛеопольд, Классный ник! smile 


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Lazin
Дата 29.6.2009, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(ЗапаснойЛеопольд @  29.6.2009,  22:36 Найти цитируемый пост)
В шаблоне передается шаблон  Я не знаю, как можно сделать удобнее не потеряв масштабируемость. Есть идеи?

можно передавать в качестве шаблонного параметра структуру, внутри которой будет шаблон

Код

struct foo
{
     template<class T> struct bar {};
};

template<class T, class Policy>
struct MyClass
{
    typedef Policy:: template bar<T> my_policy;
};


только я не очень понимаю, чем этот класс лучше обычного scoped_ptr?
PM MAIL Skype GTalk   Вверх
ЗапаснойЛеопольд
Дата 29.6.2009, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(andrew_121 @ 29.6.2009,  22:51)
ЗапаснойЛеопольд, Классный ник! smile

Сам придумал!!! smile

Добавлено @ 23:04
Цитата(Lazin @ 29.6.2009,  22:57)
только я не очень понимаю, чем этот класс лучше обычного scoped_ptr?

Ничем. Даже хуже из-за необходимости держать всё в одном контейнере. Причём всегда с виртуальным деструктором. Просто интересная головоломка... Хотя, если scoped_ptr не позволяет задавать кустарную очистку памяти (в чём я сомневаюсь)... но мне сейчас поздно лезть в boost.org , спать пора...

Код

man.push<del_single>(new ЛюбаяФигня);
man.push<clear_by_веник>(allocate_by_magic(НевообразимоКрутойКласс));

Но ведь красиво! smile

Добавлено @ 23:09
Цитата(Lazin @ 29.6.2009,  22:57)
Цитата(ЗапаснойЛеопольд @  29.6.2009,  22:36 Найти цитируемый пост)
В шаблоне передается шаблон  Я не знаю, как можно сделать удобнее не потеряв масштабируемость. Есть идеи?

можно передавать в качестве шаблонного параметра структуру, внутри которой будет шаблон

Не понял. Чем это удобнее чем man.push<garbage::del_array>(new int[10])?  smile Буду благодарен за пример...

Это сообщение отредактировал(а) ЗапаснойЛеопольд - 29.6.2009, 23:26
PM MAIL   Вверх
DrHex
Дата 30.6.2009, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Зачем вообще collector? Деструктор не годится?(collector только добовляет накладные ресурсы)


--------------------
google.com и это все.
PM MAIL   Вверх
Lazin
Дата 30.6.2009, 05:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



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

ты же попросил пример smile 
вообще, вариант, который я предложил применяется в boost.mpl, лучше он тем, что обычные шаблонные параметры проще использовать, расширяемость лучше итд...
можно еще использовать идиому traits

Код

struct del_traits
{
somewhat...
};

template<class T>
void push(T* t)
{
    typedef del_traits<T> traits;
    somewhat...
}

в этом случае тебе не нужно будет явно указывать garbage::del_array для каждого вызова, вместо этого ты можешь специализировать класс del_traits, для своего типа, и он будет использоваться в методе push 
PM MAIL Skype GTalk   Вверх
Леопольд
Дата 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   Вверх
Леопольд
Дата 1.7.2009, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Lazin @ 1.7.2009,  13:38)
кстати, стоит отметить, что сабж - вовсе не сборщик мусора smile

Пожалуй да. Но как то его обозвать надо было. Вот я и обозвал, что первое в голову пришло... smile
Пока не думал как можно было-бы заюзать его с пулом, некогда было. Возможно, для этого придётся что-нибудь изменить.
Однако если пул singleton, тогда можно будет написать политику удаления и так.

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


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


я именно об этом и говорил

А я имел ввиду совсем другое.
Какие выгоды от того что способ выделения памяти напрямую зависит от типа? Чем плохо выделять int и при помощи new, и при помощи malloc? Или пользовательский тип? Может мне надо использовать специфический тип, для которого я не хочу вызывать конструктор и деструктор, например.

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


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


Опытный
**


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

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



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

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

Я убрал вчера контейнер и сделал из объектов стек. Каждый объект удаляет предыдущий. Получается на один указатель больше чем без него, потому что надо хранить указатель на последний добавленный объект. Плюс ещё указатели на память. Недостаток в виртуальном деструкторе. Я вчера прогнал через профайлер. Больше всего времени уходит на вызов виртуального деструктора.
Вообще, можно ускорить процесс, если сделать отдельный pool для указателей а не выделять для каждого указателя новый кусочек каждый раз.
Но мне не хочется, потому что эта штука мне уже не нравится smile

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

никто не мешает мне передать в метод push что угодно smile 

И ничего удивительного. Даже константность можно снять приведением типов. Это С++.
Код

Foo* ptr = (Foo*)malloc(sizeof(Foo));
boost::shared_ptr<Foo>(ptr);

Даже если привязать способ очистки памяти к типу объекта при помощи traits, то что сможет помешать выделить память иначе для этого же объекта? Например, при помощи malloc... Тут уже всё зависит от программиста.

Но можно привязать способ очистки к способу выделения памяти а не к типу объекта. Я полагаю, mes, имел ввиду именно это.

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


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


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


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

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



Цитата(Леопольд @  1.7.2009,  17:06 Найти цитируемый пост)
Я убрал вчера контейнер и сделал из объектов стек. Каждый объект удаляет предыдущий.

Позвольте узнать зачем ? а также хотелось бы услышать какую задачу должен решать Ваш компонент ? (а то обсуждаем зверя о сути которого нам практически ничего неизвестно smile )

Цитата(Леопольд @  1.7.2009,  17:06 Найти цитируемый пост)
Больше всего времени уходит на вызов виртуального деструктора.

А зачем Вам вообще обязательный виртуальный деструктор ? 

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

И ничего удивительного. Даже константность можно снять приведением типов. Это С++.

А не объясните ли, как Ваше сравнение вяжется с контекстом замечания ?! 

Цитата(Леопольд @  1.7.2009,  17:06 Найти цитируемый пост)
Но можно привязать способ очистки к способу выделения памяти, а не к типу объекта.Я полагаю, mes, имел ввиду именно это.

 smile



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


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


Опытный
**


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

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



Цитата(mes @ 1.7.2009,  20:20)
Цитата(Леопольд @  1.7.2009,  17:06 Найти цитируемый пост)
Я убрал вчера контейнер и сделал из объектов стек. Каждый объект удаляет предыдущий.

Позвольте узнать зачем ? а также хотелось бы услышать какую задачу должен решать Ваш компонент ? (а то обсуждаем зверя о сути которого нам практически ничего неизвестно smile )

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

На мой взгляд, идея о жёсткой связи способа выделения и способа освобождения памяти очень хороша.

Добавлено @ 20:31
Цитата(mes @ 1.7.2009,  20:20)
Цитата(Леопольд @  1.7.2009,  17:06 Найти цитируемый пост)
Цитата(Леопольд @  1.7.2009,  17:06 Найти цитируемый пост)
никто не мешает мне передать в метод push что угодно smile 

И ничего удивительного. Даже константность можно снять приведением типов. Это С++.

А не объясните ли, как Ваше сравнение вяжется с контекстом замечания ?!

Именно с контекстом, никак. Но смысл есть... smile Всегда можно сделать не так как предназначено.

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


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


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


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

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



Цитата(Леопольд @  1.7.2009,  19:29 Найти цитируемый пост)
Именно с контекстом, никак. Но смысл есть... smile Всегда можно сделать не так как предназначено.

"снять константность" это предназначение инструмента для решения определенной проблемы
"передать в метод push что угодно " - это недоработка инструмента, позволяющего создать некоторые непредвиденные проблемы.

разницу надеюсь почувствовали smile

Цитата(Леопольд @  1.7.2009,  19:29 Найти цитируемый пост)

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

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



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


Бывалый
*


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

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



Цитата

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


Поддержую.....

Для сборки мусора, а точнее освобождению освобождения линамической памяти можно, используются smart-poiner, а фантаций в их реализации куча. Можно есче конечно написать аллокатор, и использовать как для выделения памяти так и для освобождения. Но выделять память, а потом добовлять указатели на эту память в контейнер что бы потом удалить, это нонсанс!!!
 



--------------------
google.com и это все.
PM MAIL   Вверх
Lazin
Дата 2.7.2009, 05:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Леопольд @  1.7.2009,  18:06 Найти цитируемый пост)
Но можно привязать способ очистки к способу выделения памяти а не к типу объекта
вывод конечно гениальный, но по моему это и так очевидно, и все с этим согласны.. smile

Цитата(Леопольд @  1.7.2009,  18:06 Найти цитируемый пост)
И ничего удивительного. Даже константность можно снять приведением типов. Это С++

когда речь идет о интерфейсе класса, то желательно, что-бы он был сделан так, что-бы не допустить возможность неправильного использования smile 
PM MAIL Skype GTalk   Вверх
Леопольд
Дата 2.7.2009, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Всем спасибо! Противопоставить нечего, потому что сам думаю так же...


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

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

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

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

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


 




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


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

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