Создание объекта с подсчетом ссылок в D с использованием RefCounting! (T) - PullRequest
8 голосов
/ 08 января 2011

Как вы используете std.typecons.RefCounted!(T) для создания объекта с подсчетом ссылок в D?

Я пытался выяснить, что std.array.Array внутренне делает, глядя на источник, но пока я могу читатьисточник, я просто не могу понять, что такое «полезная нагрузка» или как все это работает, когда есть такие вещи, как побитовое структурное копирование, а также почему некоторые вещи дублируются во внутренней и внешней структуре.Может ли кто-нибудь предоставить пример или ссылку на то, как его использовать, скажем, для упаковки простого Win32 HANDLE?

Спасибо!

1 Ответ

9 голосов
/ 08 января 2011

Отказ от ответственности: я не проверял свои заявки, просто прочитал документацию .

Полезная нагрузка относится к тому, что хранится.В вашем случае полезной нагрузкой является Win32 HANDLE.Поскольку HANDLE - это просто целое число, которое вы не захотите делать:

auto refHandle = RefCounted!HANDLE(WhatGetsMeAHandle());

Поскольку функция Windows должна вызываться, когда дескриптор выходит из области видимости.

В std.containers.Массив, который вы видели, был структурой с именем Payload, в которой было поле с именем _payload.Структура будет хранилищем данных, доступ к которым осуществляется через _payload.Это обеспечивает уровень косвенности, который будет использоваться позже.

Вы заметите, что RefCounts фактически используется в структуре Array .Это означает, что деструктор для этой структуры будет вызываться только тогда, когда счетчик ссылок равен 0. Так что ~ this () внутри Payload - это место, где вы хотите очистить вашу РУЧКУ.

Что происходит: с тех порstruct является типом значения, каждый раз, когда структура выходит из области видимости, вызывается деструктор, для Array его нет, но полезная нагрузка оборачивается в RefCounting, также вызывается деструктор для RefCounting! Payload.И только когда счетчик ссылок достигает нуля, вызывается деструктор для самой полезной нагрузки.

Теперь сам RefCounts имеет семантику ссылок, это означает, что, имея массив a, вы можете присвоить auto b = a;и все будет скопировано, но в RefCounts определены постблиты , означающие, что данные не будут скопированы, но счетчик ссылок будет увеличен.

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

struct MyWinWrapper {
    struct Payload {
        HANDLE _payload;
        this(HANDLE h) { _payload = h; }
        ~this() { freeHandleHere(_payload); }

        // Should never perform these operations
        this(this) { assert(false); }
        void opAssign(MyWinWrapper.Payload rhs) { assert(false); }
    }

    private alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data;
    private Data _data;

    this(HANDLE h) { _data = Data(h); }
}

Поскольку для структуры не существует конструктора по умолчанию, вы, вероятно, захотите предоставить бесплатную функцию, которая возвращает эту структуру.

...