8

你如何std.typecons.RefCounted!(T)在 D 中创建一个引用计数的对象?

我试图通过查看源代码来弄清楚std.array.Array内部是做什么的,但是虽然我可以阅读源代码,但我只是无法弄清楚“有效负载”是什么,或者当涉及到按位结构复制之类的事情时它是如何工作的,以及为什么有些东西在内部和外部结构中是重复的。

谁能提供一个示例或链接来说明如何使用它来包装一个简单的 Win32 HANDLE

谢谢!

4

1 回答 1

9

免责声明:我没有测试我的声明,只是阅读文档

有效负载是指正在存储的内容。在您的情况下,有效负载是 Win32 HANDLE。由于 HANDLE 只是一个整数,你不想这样做:

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

因为当句柄超出范围时需要调用 Windows 函数。

在 std.containers.Array 中,您看到的是一个名为 Payload 的结构,它有一个名为 _payload 的字段。该结构将是数据的存储,通过_payload访问。这提供了稍后使用的间接级别。

您会注意到 RefCounted 实际上用于 Array 结构。这意味着只有当引用计数为 0 时才会调用该结构的析构函数。因此 Payload 内部的 ~this() 是您想要清理 HANDLE 的地方。

发生了什么:由于 struct 是一种值类型,每次结构超出范围时都会调用析构函数,Array 没有析构函数,但是 Payload 被包装在 RefCounted 中,RefCounted!Payload 的析构函数也被调用。只有当引用计数达到零时,才会调用 Payload 本身的析构函数。

现在,RefCounted 本身具有引用语义,这意味着拥有一个数组 a,然后您可以分配给 auto b = a; 并且所有内容都将被复制,但 RefCounted定义了一个 postblits ,这意味着数据不会被复制,但引用计数将增加。

我现在将尝试为您提供您想要的包装大纲。它可能会帮助您将上述信息可视化,但可能并不完全正确。让我知道是否需要修复。

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); }
}

由于结构没有默认构造函数,您可能希望提供一个返回此结构的免费函数。

于 2011-01-08T17:11:53.723 回答