Модераторы: 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   Вверх
Страницы: (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.1185 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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