Подтвердить что ты не робот

С++/CX обнаруживает и решает циклы объектов?

Из моего понимания С++/CX не использует сбор мусора, вместо этого использует подсчет ссылок.

Проблема с подсчетом ссылок заключается в том, что он не может избавиться от циклов. Циклы обычно решаются с использованием слабых ссылок, таких как weak_ptr в стандартном С++.

Но я не могу найти способ в С++/CX явно указать слабую ссылку. Из этого я бы предположил, что это обрабатывается самим С++/CX. Мне интересно, как С++/CX решит это.

Например, посмотрите на следующий код:

ref class Foo
{
public:
    Bar^ bar;
};

ref class Bar
{
public:
    Foo^ foo;
};

ref class App
{
public:
    virtual void OnLaunched(LaunchActivatedEventArgs^ args)
    {
        Foo^ foo = ref new Foo();
        Bar^ bar = ref new Bar();
        foo.bar = bar;
        bar.foo = foo;
    }
};

Как С++/CX обнаруживает этот цикл?

Как С++/CX разрешает этот цикл?

Как С++/CX решает, какой из этих объектов должен быть "корневым объектом", а какой должен быть "слабая ссылка"?

4b9b3361

Ответ 1

Короткий ответ: Нет, С++/CX не обнаруживает и не разрешает циклы объектов.

Длинный ответ: сам WinRT имеет стандартный механизм для слабых ссылок. На уровне ABI это определяется в терминах интерфейсов IWeakReference и IWeakReferenceSource, которые вы можете увидеть в разделе "% ProgramFiles%\Windows Kits\8.0\Include\winrt\WeakReference.idl".

В С++/CX все ваши классы будут автоматически реализовывать IWeakReferenceSource, и, следовательно, все их экземпляры могут быть слабо указаны. Чтобы получить и сохранить слабую ссылку на объект, вы должны использовать вспомогательный класс Platform::WeakReference (определенный в файле vccorlib.h):

Foo^ foo = ref new Foo;
Platform::WeakReference weakRef(foo);

чтобы вернуть объект назад, используйте Resolve<T>:

foo = weakRef.Resolve<Foo>();

Как обычно, вы получите nullptr, объект уже уничтожен.

Кроме того, экземпляр WeakReference ведет себя более или менее как интеллектуальный указатель - он может быть скопирован, перемещен, сопоставим, присваивается из nullptr, имеет неявное преобразование в неопределенный тип bool и т.д.

Обратите внимание, что с VS11 Beta IDE Intellisense перестанет работать с WeakReference, если вы попытаетесь использовать ее, подчеркнув ее с помощью squiggles и т.д. Компилятор может справиться с ними просто отлично, несмотря на все это.

Ответ 2

Отметьте Include\winrt\WeakReference.h в SDK. Он определяет IWeakReference, который может быть использован для этой цели.

Ответ 3

Это будет тот же старый способ программирования COM, ручного мышления и добавления явных вызовов denf.

Ответ 4

Как сказал Павел Минаев, WinRT имеет стандартный механизм для слабых ссылок: интерфейсы IWeakReferenceSource/IWeakReference, вспомогательный класс WRL::WeakRef и т.д.

К сожалению, классы, определенные через ref class, не реализуют IWeakReferenceSource и, по крайней мере, в этой версии предварительного просмотра для разработчиков, я не смог найти способ добавить этот интерфейс.

Возможным обходным решением является внедрение класса WinRT без использования расширений С++/CX в "native" С++. Структура WRL значительно упрощает эту задачу (для WinRT это делает ATL для COM).

Существует один из образцов WinRT (образец "Authoring" для DLL-сервера), который показывает, как реализовать объект WinRT без использования ref. По умолчанию классы, наследующие от WRL::RuntimeClass<Interface>, автоматически реализуют IWeakReferenceSource и поэтому предоставляют слабые ссылки.

Ответ 5

Mozilla XPCOM реализовал подход Bacon, и этот в какой-то степени можно портировать в WinRT если нужно. Вообще, избегать трассировки сборщика мусора - это хорошо. Разработчики по-прежнему имеют множество способов утечки памяти, поэтому лучше не впадать в заблуждение. Кроме того, с точки зрения контроля, циклическая собственность не имеет смысла. Это, как Мюнхгаузен, вытаскивает себя из грязи собственными волосами и держит себя в воздухе. Должна быть причина для существования каждого объекта, и подсчет ссылок является проявлением этой причины. Еще одно проявление - это право на изменение, которое порождает надежные методы копирования на запись, сильно зависящие от доступности счетчика. В средах, где есть только трассировка сборки мусора, либо приходится выполнять глубокую копию изменяемых структур данных, чтобы сохранить ее от нежелательных мутаций, либо использовать неизменные структуры данных с большими штрафами за небольшие глубокие изменения. Или конвертировать изменяемые и неизменные структуры данных взад и вперед. Кроме того, было подсчитано, что трассировка коллекции мусора работает отлично, когда доступно 5-кратное требуемое ОЗУ [ глубоко скопированные реплики не учитываются). Для сравнения, консервативные распределители используют 2x требуемую ОЗУ (впустую из-за фрагментации). Не обманывайте, копирование сборщика мусора только делает распределение быстрее, но тратит в 2,5 раза больше оперативной памяти, чем справочный подсчитанный консервативный сборщик мусора для достижения сопоставимой производительности.

Посмотрите на Apple. Они представили TGC в Objective-C 2.0 в качестве дополнительной функции, но затем отказались от нее, и тонны приложений iPhone живут без особого труда. iPhones известны отличным пользовательским интерфейсом и длительной продолжительностью заряда аккумулятора. Windows 10 зависает как ад на моем 4Gb RAM ПК, в то время как Mac OS X 10.4.10 Hackintosh работал довольно гладко на 1 Гб оперативной памяти. Может быть, это так или иначе связано, не так ли? Может быть, память случайно просочилась где-то, но в конце ее трудно наблюдать по сравнению с замораживанием и огромным потреблением RAM.

Огромное потребление оперативной памяти заставляет программы обмениваться на диск, и если они поменялись на диск, а затем начали отслеживать сборку мусора, все обменные страницы возвращаются в ОЗУ, а перемещение поменяемых страниц обратно в ОЗУ заметно медленное. Кроме того, при этом страницы других приложений должны быть предварительно выгружены для обмена файлами. Как мы знаем, трассировка сборщиков мусора использует в 2,5 раза больше оперативной памяти, поэтому у этих приложений в 2,5 раза больше шансов поменяться местами. Внезапно другое приложение также инициирует сборку мусора и должно будет поменять местами страницы обратно в ОЗУ, выгружая страницы других приложений. И он идет и идет как вечный двигатель, наоборот. Обычный вечный двигатель бесконечно вырабатывает энергию из воздуха, а вечный двигатель, наоборот, бесконечно тратит энергию на нет. Трассировка сборки мусора - это алгоритм, который никогда не заканчивается. Время от времени оно инициируется эвристически, и это известно только тогда, когда это было сделано, если ему повезло. Возможно, на этот раз нам повезет что-нибудь собрать, может быть, второй раз, может быть, в третий раз. Вы оставляете ПК в течение долгого времени, надеясь, что в конечном итоге он будет заниматься своим делом и, наконец, позволит вам работать, но этот бизнес никогда не заканчивается. Внезапно два приложения запускают трассировочную сборку мусора в одно и то же время и начинают соревноваться за нераспределенное ОЗУ. Трассировка сбора мусора, вероятно, сделает несколько последующих обращений к одной и той же странице, поэтому одна страница может переходить и меняться несколько раз. В офисных средах только босс-ПК, скорее всего, будет иметь много оперативной памяти, другие ПК как можно дешевле. Кроме того, антивирус принудительно развертывается на всех офисных ПК, а сотрудники офиса не могут избавиться от него. Антивирус сохраняет ОЗУ для подписи в памяти, что делает его еще более слабым, а также проверяет, все ли операции ввода-вывода, включая swap файл, зависают, чтобы завершить безумие. Это где ад на Земле.

Я попросил адвокатов по сборщикам мусора, если они могут наблюдать за заморозками, как я, и получается, что они помещают много ОЗУ в свои ПК (например, 16 ГБ на ноутбуке!!!), используйте его в режиме одного пользователя, и сборщик мусора отлично подходит для них таким образом. В аду им придется работать со своими разработками на самых дешевых офисных ПК с антивирусным программным обеспечением, развернутым.

Поэтому я предлагаю вам не рассматривать проблему цикла. Научитесь любить подсчет ссылок, НАСЛАЖДАЙТЕСЬ И сделайте, чтобы пользователи наслаждались вашими тонкими программами. Сделайте большую часть подсчета ссылок. Надежная копирование на запись для вложенных структур. Пулы подключения к базе данных с завернутыми соединениями, когда соединения возвращаются в пул сразу же, когда их обертка больше не ссылается. Прозрачность сети. RAII.

И если у вас действительно нет других вариантов, заимствуйте у Mozilla XPCOM. Кстати, на ОС Windows Mozilla XPCOM говорят, что ABI идентичен ABI, но не уверен.

Ответ 6

Это не объекты WinRT, это объекты вашего настраиваемого типа. Поскольку вы указали их как типы ссылок .NET(ref class) с использованием синтаксиса С++/CLI, они собираются как мусор, как и все типы ссылок .NET, с помощью теста достижимости, а не подсчета ссылок.

Объекты Win32 всегда подсчитывались, поэтому WinRT ничего не меняет. Он просто предоставляет классы С++ RAII для вас, под Win32 программисты написали свои собственные обертки, чтобы воспользоваться RAII.