LINUX.ORG.RU

Ответ на: комментарий от emulek

Как ты будешь строить сборку для

class A : public GC
{
// ...
};

class B : public GC
{
// ...
private:
    A field1;
};

class C : public GC
{
// ...
private:
    A field1;
    B field2;
};

anonymous
()
Ответ на: комментарий от anonymous

Тут вообще gc не нужен.

ну да, в Java нужен, а в C++ значит, такой же — не нужен.

Слив засчитан. GC это _алгоритм_ управление памятью, а не какие-то «шаблоны», и «llvm».

emulek
()
Ответ на: комментарий от anonymous

Как ты будешь строить сборку для

никак. Сборка у меня только для _данных_ A, B, и C. И все эти данные выделяются например оператором GC::new. Сами объекты классов-наследников GC НЕ управляются GC, как и сам базовый класс GC.

Или ты настолько упорот, что хочешь создать GC, который управляет объектами GC? Т.е. сам собой?

emulek
()
Ответ на: комментарий от emulek

ну да, в Java нужен, а в C++ значит, такой же — не нужен.

В Java он используется, просто потому, что он уже есть для остального и нет никакого смысла прикручивать что-то еще. Это простейший случай владения, с которым С++ прекрасно справляется.

GC это _алгоритм_ управление памятью

GC - это сборщик мусора. Там несколько стадий со своими алгоритмами. Кроме того, у сборки мусора много разновидностей. Но то, что ты показываешь, это просто RAII.

GC с момента своего появления работает не просто с памятью, а с графом объектов. Так было в первом Лиспе с GC, так сейчас в JVM, .NET, etc.

anonymous
()
Ответ на: комментарий от anonymous

GC - это сборщик мусора. Там несколько стадий со своими алгоритмами. Кроме того, у сборки мусора много разновидностей. Но то, что ты показываешь, это просто RAII.

покажи мне «не просто RAII».

ЗЫЖ я прекрасно знаю про «множество разновидностей», потому и не могу тебе вот сейчас взять, и отлить серебряную пулю для всего.

В C++ разновидностей ещё больше, ибо ты не ограничен тем, что тебе дали.

emulek
()
Ответ на: комментарий от emulek

Или ты настолько упорот, что хочешь создать GC, который управляет объектами GC?

Это ты зачем-то наследуешь классы от сборщика мусора. Не надо перекладывать с больной головы на здоровую.

никак.

Тогда и сборки у тебя нет. И да, такая «сборка» уже есть в стандартной библиотеке. Причем в более обобщенном и красивом виде. std::unique_ptr, std::shared_ptr, std::weak_ptr + свой аллокатор и все. Но я тебе еще раз говорю, это не полноценная сборка мусора.

anonymous
()
Ответ на: комментарий от emulek

покажи мне «не просто RAII»

Да тебе миллион раз показывали примеры. Ты придирался к обозначениям в псевдокоде. К ref, к <> и пр. И даже когда это все убрали - просто ушел от ответа и начал говорить, что объект A не в куче, хотя автор примера тебе сказал, что именно там.

anonymous
()
Ответ на: комментарий от anonymous

Это ты зачем-то наследуешь классы от сборщика мусора.

это для того, что-бы сборщик мусора мог управлять разными объектами. Вот класс A у меня работает со строками, ну типа твоего String'а. И в классе A есть специфические операторы, вроде operator+, который реализует конкатенацию строк. Но с памятью он НЕ работает. Вообще. Память выделяет/освобождает базовый класс GC, который понятия не имеет о строках A, и для которого «строка» — просто набор байтов. Он знает их число, знает их адрес, и знает, КОМУ они принадлежат (ибо он — базовый класс. Ему и принадлежат)

Тогда и сборки у тебя нет. И да, такая «сборка» уже есть в стандартной библиотеке. Причем в более обобщенном и красивом виде. std::unique_ptr, std::shared_ptr, std::weak_ptr + свой аллокатор и все. Но я тебе еще раз говорю, это не полноценная сборка мусора.

это вообще другое. Набор гаечных ключей ничем не лучше и не хуже набора отвёрток. А про «красиво» — это ты не по адресу.

emulek
()
Ответ на: комментарий от anonymous

И даже когда это все убрали - просто ушел от ответа и начал говорить, что объект A не в куче, хотя автор примера тебе сказал, что именно там.

автор примера — <нечто обидное>. Откуда такая узость мышления? Почему в Java объектом может быть что угодно, а в C++ только глупый указатель/ссылка? Почему в этом ВАШЕМ C++ сборщик мусора может оперировать только непосредственно с переменными самого ЯП, а не через некий интерфейс?

emulek
()
Ответ на: комментарий от emulek

Вот класс A у меня работает со строками, ну типа твоего String'а. И в классе A есть специфические операторы, вроде operator+, который реализует конкатенацию строк. Но с памятью он НЕ работает. Вообще. Память выделяет/освобождает базовый класс GC, который понятия не имеет о строках A, и для которого «строка» — просто набор байтов.

В стандартной библиотеке С++ за это же самое отвечают аллокаторы. Это GC, да?

anonymous
()
Ответ на: комментарий от emulek

Откуда такая узость мышления? Почему в Java объектом может быть что угодно, а в C++ только глупый указатель/ссылка?

Я не понимаю, как из того примера можно сделать такой вывод. Нет, используй что хочешь. Любые объекты. Только покажи сборку мусора, черт возьми.

anonymous
()
Ответ на: комментарий от anonymous

В стандартной библиотеке С++ за это же самое отвечают аллокаторы. Это GC, да?

ВНЕЗАПНО: да. Ты некогда не задумывался, на кой ляд new/delete можно перезагружать? Вот именно для того, что-бы делать свои GC СБИШ.

emulek
()
Ответ на: комментарий от anonymous

Я не понимаю, как из того примера можно сделать такой вывод. Нет, используй что хочешь. Любые объекты. Только покажи сборку мусора, черт возьми.

НЕ ТАКИЕ. Я в толк взять никак не могу, почему ты хочешь, что-бы GC убирал именно ЭТОТ класс? Почему это не пойдёт? Есть ли под С++ годные библиотеки для веб девелопмента? (комментарий)

emulek
()
Ответ на: комментарий от anonymous

Почему другое, если они делают именно то, что ты описал?

отвёртки и гаечные ключи тоже ДЕЛАЮТ именно то — откручивают/закручивают. Но да, отвёрткой болт и гайку закручивать несподручно.

emulek
()
Ответ на: комментарий от anonymous

Подключайся.

ладно

И как внешний сборщик будет строить граф объектов, определять рутовые ссылки и пр.? Сборщик мусора работает не просто с памятью, а с графом объектов.

0. собираемые gc ссылки назовем сильными ссылками, на с++ они будут HardRef<T>

1. картой памяти назовем битовую карту, где бит i установлен, если по адресу 4*i лежит 4-ка байт, представляющая собой HardRef<T>; эти биты будут устанавливаться в момент конструирования HardRef<T> его конструктором (для простоты говорим о 32 битах; в 64 почти то же самое)

2. именно граф объектов, кажется, строить не обязательно, но если уж мы собрались перемещать объекты, то пусть T обязан иметь таблицу виртуальных функций; тогда можно узнать sizeof(T) либо через компиляторную магию, либо через требование для T иметь в виде предка че-то-там с методом size_of_me(); дальше смотрим установленные биты в карте памяти, и трассируем эти указатели

3. рутовые ссылки: пусть все my_hard_ref->payload аллоцируются в определенной арене; тогда рутовые ссылки будут все те, у кого установлен бит в карте памяти, но лежит вне арены

4. перемещение: делается стандартно, кажется это называется self-references в uniprocessor garbage collection technics или как там его

насчет тормозов: да, карта памяти объекта будет делаться нерационально, но и тут можно подставить костылики; насчет карты памяти фрейма стека функции — ты прям вот уверен, что она всегда одна и та же? я — нет

 
int f(int i) {
  ....
  if(random()<....) {
    Some_object_with_hard_refs o1 = ....
  }else{
    Other_object_with_hard_refs o2 = ....
  }
  ....
}

объектам о1 и о2 может быть выделено одно и то же место на фрейме

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от anonymous

виртуальный T::size_of_me() похоже можно сделать через костыли на стандартном с++, ну или совсем чуть-чуть пропатчить компилятор, но вообще, конечно, поддержка со стороны компилятора не помешала бы

например, компилятор с++ будет разрешать иметь обычные ссылки на поля объекта, который создан через HardRef

в общем, по-хорошему нужен нормальный язык

да, еще KblCb спрашивал «Каким образом он разберётся?» — ответ комментом выше

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

в общем, по-хорошему нужен нормальный язык

Зачетный вывод=)

anonymous
()
Ответ на: комментарий от www_linux_org_ru

картой памяти назовем битовую карту, где бит i установлен, если по адресу 4*i лежит 4-ка байт, представляющая собой HardRef<T>; эти биты будут устанавливаться в момент конструирования HardRef<T> его конструктором (для простоты говорим о 32 битах; в 64 почти то же самое)

зря ты про эту схему вспомнил ИМХО. Очевидно жеж, что она ненадёжна.

emulek
()
Ответ на: комментарий от www_linux_org_ru

насчет карты памяти фрейма стека функции — ты прям вот уверен, что она всегда одна и та же? я — нет

посмотри на рекурсивный обход бинарного дерева — там фрейм стека прямо зависит от данных.

emulek
()
Ответ на: комментарий от anonymous

Ну мля, это не GC. Это различные алгоритмы распределения памяти.

а что такое по твоему GC, как не алгоритм распределения памяти?

emulek
()
Ответ на: комментарий от anonymous

Да, вроде должно работать в первом приближении.

эта NIH работает. Я даже такое видел. Вот только ИМХО поддерживать её — Адъ и Израиль.

emulek
()
Ответ на: комментарий от www_linux_org_ru

3. рутовые ссылки: пусть все my_hard_ref->payload аллоцируются в определенной арене; тогда рутовые ссылки будут все те, у кого установлен бит в карте памяти, но лежит вне арены

Можно чуть подробнее на этом месте? Я пока не сообразил что ты имеешь в виду.

KblCb ★★★★★
()
Ответ на: комментарий от KblCb

а что конкретно не ясно?

(рутовые ссылки — это те ссылки, которые безусловно удерживают объект, и начиная с которых можно trace-ить)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от anonymous

тут имеется в виду, что если сама ссылка находится не в куче сборщика, то она в руте

Чёрт. Элегантно. Снимаю шляпу.

KblCb ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Отлично. Кстати, несколько похоже на то, что я обдумывал, только у меня был список ссылок, а не битовая карта. С помощью битовой карты (кажется) можно обходить поля-ссылки, не строя никаких графов и достаточно быстро.

И еще я не догадался, что все вне арены можно считать рутом. Это просто гениально, мне кажется =)

пусть T обязан иметь таблицу виртуальных функций; тогда можно узнать sizeof(T) либо через компиляторную магию, либо через требование для T иметь в виде предка че-то-там с методом size_of_me(); дальше смотрим установленные биты в карте памяти, и трассируем эти указатели

Хм. Вот я, например, предполагал получать размер при создании и хранить вместе с объектом. Если мы делаем какую-нибудь gc_new<A>(x,y,z), то мы делаем ее шаблонным и имеем всю информацию о типе, какую можно получить на статике. Если же мы переопределяем new или делаем свой аллокатор, то просто считаем объектом весь запрашиваемый объем памяти(а размером - переданный нам размер). Разве этого не достаточно?

перемещение: делается стандартно, кажется это называется self-references в uniprocessor garbage collection technics или как там его

В контексте С++ приходится накладывать ограничение на указатели на члены, на внутренние сырые и не очень указатели на поля и пр. и пр. Я не знаю, как запретить такие вещи даже с помощью шаблонной магии... Потому, честно говоря, не уверен, стоит ли вообще делать перемещающий сборщик для С++. Впрочем, это можно сделать лишь одной из его стратегий.

forCe
()
Ответ на: комментарий от forCe

В контексте С++ приходится накладывать ограничение на указатели на члены, на внутренние сырые и не очень указатели на поля и пр. и пр.

ты всё делаешь не так.

1. делаем все объекты на стеке (на самом деле не обязательно, мне так проще описывать)

2. корневая ссылка создаётся в конструкторе по умолчанию

3. есть список корневых ссылок (не обязательно это список)

4. оператор/конструктор копирования создаёт некорневую ссылку

5. когда объект уходит из области видимости, он становится мусором. Если это корневая ссылка, она замещается какой-то своей некорневой, если некорневых нет, то удаляется из списка корневых

6. можно делать массивы. Для этого перезагружаются []. Массивы могут индексироваться любыми объектами. И содержать любые объекты. operator[] отдаёт умный указатель, которому можно присваивать, и который можно использовать вместо объекта.

7. можно делать списки. Если к примеру для integer определён print(), то list->head->print() тоже работает, за счёт перезагрузки ->. (селектор класса тоже можно перезагружать, причём многократно)

8. можно делать всякие другие групповые объекты. (деревья и проч.)

9. массивы C++, глупые указатели, и проч. просто НЕ ИСПОЛЬЗУЮТСЯ.

emulek
()
Ответ на: комментарий от emulek

т.е. видимо ошибка в том, что когда явист видит

X->Y
он думает: Ага! Это объект X какого-то класса, и берётся его поле Y по смещению от адреса в памяти X! Сборка мусора невозможна!

На самом деле, это никакой НЕ адрес и НЕ смещение. "->" это ФУНКЦИЯ. И нужна она здесь для того, что-бы X вёл себя как Y. Т.е. делегировал свой функционал Y. Если Y это строка, то и X->Y тоже строка, и с ней можно делать тоже самое, что с любой строкой. В том числе, GC может сдвинуть её данные выше на 12783 байтов. Потому-что это никакое не смещение, ни какого адреса.

emulek
()
Ответ на: комментарий от emulek

Ты бы лучше учился у www_linux_org_ru. Пара сообщений в треде, все конструктивно и понятно. У тебя тут 100500 сообщений и все не о том...

forCe
()
Ответ на: комментарий от forCe

Все тут понимают о чем речь, а уж С++ знают не хуже тебя.

тогда почему не пишете на C++?

Ты бы лучше учился у www_linux_org_ru

угу. Тонкий тролль: пришёл, обмазался всякими битовыми картами и глупыми указателями, и наглядно «доказал», что C++ не годен. То есть вообще никуда.

emulek
()
Ответ на: комментарий от emulek

forCe вроде как раз плюсовик и сишник. А 'тролль' как раз по делу все написал и честно сказал, что у с++ тут есть ряд проблем, которые мог бы решить компилятор

anonymous
()
Ответ на: комментарий от anonymous

А 'тролль' как раз по делу все написал и честно сказал, что у с++ тут есть ряд проблем, которые мог бы решить компилятор

проблема тут всего одна: когда мы смотрим на сишный указатель(ссылку), мы видим 0x234DF3430. ВСЁ. Да, без libaastral'а нет никакой возможности выяснить, что эта за хрень, откуда она взялась, и даже её размер непонятен (ибо это может быть массив, одиночный эл-т, и даже голова списка/дерева. Sizeof даст размер одного эл-та по любому)

Я вам уже сказал, что надо всё наследовать от общего предка, который и будет следить(и запоминать) за тем, что откуда взялось. Тогда при запуске GC, мы можем это всё восстановить, и выяснить, что уже мусор, а что — нет. Можем и больше — можем циклы, можем нелинейные графы, можем поколения, можем вообще ВСЁ.

«зависших» ссылок у нас не получается потому, что operator=() перегружен. И мы никак не можем затереть и повесить ссылку.

раньше освободить объект тоже не получается, ибо delete и деструктор тоже перегружены, и НЕ станут возвращать в кучу указатель, который ещё используется.

Т.е. мы можем сделать php::unset(obj); который создаёт новый пустой obj на месте старого. При этом кажется, что obj «очистился», но это не так. На самом деле, этот объект стал не нужным 'obj'. Если он больше никому не нужен, мы его можем сразу удалить, а можем оставить это GC.

И обмазываться глупыми указателями совсем не обязательно, и даже не нужно. Но можно, да. Никто не запрещает, это не java, и тут вам никто не мешает отстрелить себе яйца.

emulek
()
Ответ на: комментарий от emulek

тогда почему не пишете на C++?

Последние лет шесть пишу в основном только на крестах.

угу. Тонкий тролль: пришёл, обмазался всякими битовыми картами и глупыми указателями, и наглядно «доказал», что C++ не годен. То есть вообще никуда.

Что такое по твоему умные указатели и как они реализуются в крестах?

KblCb ★★★★★
()
Ответ на: комментарий от emulek

Он обмазался умными указателями - HardPtr<T> или как там.

anonymous
()
Ответ на: комментарий от KblCb

Что такое по твоему умные указатели и как они реализуются в крестах?

ИМХО лучше тебе прочитать книжку Джеффа Элджера. Зачем тебе меня слушать?

emulek
()
Ответ на: комментарий от emulek

Судя по всему, прочесть ее надо тебе. Хотя она и старовата.

А то ты почему-то видишь глупые указатели там, где люди пишут об умных.

anonymous
()
Ответ на: комментарий от anonymous

А то ты почему-то видишь глупые указатели там, где люди пишут об умных.

эти недостаточно умные для реализации GC. Только с костылями, как тут предложили.

emulek
()
Ответ на: комментарий от emulek

эти недостаточно умные для реализации GC.

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

anonymous
()
Ответ на: комментарий от anonymous

использование твоего GC не просто не даст преимуществ, а будет хуже ручного управления памятью.

можно пример кода, в котором это высказывание истинно?

emulek
()
Ответ на: комментарий от emulek

Ты пока даже не привел дельного использования своего «GC», что в купе с весьма мутным описанием и каким-то списком ограничений, дает основания предполагать, что с любого примера ты съедешь, как и со всех примеров, приводимых тебе в этой теме. Поэтому давай ты приведешь какой-нибудь фрагментик использования объектов твоего GC.

А пока я тебе отвечу, что любые объекты в куче, содержащие в себе ссылки на другие объекты в куче и т.д. использовать в твоем «GC» будет очень неудобно, если вообще возможно...

anonymous
()
Ответ на: комментарий от www_linux_org_ru

картой памяти назовем битовую карту, где бит i установлен, если по адресу 4*i лежит 4-ка байт, представляющая собой HardRef<T>; эти биты будут устанавливаться в момент конструирования HardRef<T> его конструктором (для простоты говорим о 32 битах; в 64 почти то же самое)

Для 64 битов полная битовая карта потребует несколько сотен миллионов гигов памяти(лень точно считать). Ты уверен, что хочешь этого? Для 32 вроде нормально, 64 мега.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.