使用 RefCounted!(T) 在 D 中创建引用计数对象

发布于 2024-10-10 19:34:59 字数 261 浏览 9 评论 0原文

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

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

任何人都可以提供有关如何使用它来包装简单的 Win32 HANDLE 的示例或链接吗?

谢谢!

How do you use std.typecons.RefCounted!(T) to make a reference-counted object in D?

I've tried to figure out what std.array.Array does internally by looking at the source, but while I can read the source, I just can't figure what a "payload" is or how it all works when there's things like bitwise struct copying involved, as well as why some things are duplicated in the internal and external structure.

Could anyone provide an example or a link on how to use it to, say, wrap a simple Win32 HANDLE?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

假装不在乎 2024-10-17 19:34:59

免责声明:我尚未测试我的主张,只需阅读文档

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

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

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

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

您会注意到 RefCounted 实际上用在数组上结构。这意味着只有当引用计数为 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); }
}

由于结构没有默认构造函数,您可能需要提供一个返回该结构的自由函数。

Disclaimer: I haven't tested my claims, just read the documentation.

Payload is referring to what is being stored. In your case the payload is the Win32 HANDLE. Since HANDLE is just an integer you wouldn't want to do:

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

Because a Windows function will need to be called when the handle goes out of scope.

In std.containers.Array what you saw was a struct called Payload, which had a field called _payload. The structure is going to be the storage of the data, accessed through _payload. This provides a level of indirection to be utilized later.

You will notice that RefCounted is actually used on the Array structure. This means the destructor for that struct will only be called when the reference count is 0. So the ~this() inside of Payload is where you would want to clean up the your HANDLE.

What is happening: since struct is a value type, every time the structure goes out of scope the destructor is called, there isn't one for Array, but Payload is wrapped in a RefCounted, the destructor for RefCounted!Payload is also called. And only when the reference count reaches zero is the destructor for Payload itself called.

Now, RefCounted itself has reference semantics, this means that having an Array a, you can then assign to auto b = a; and everything will be copied over, but RefCounted has a postblits defined meaning the data will not be copied, but the reference count will be
incremented.

I will now try and provide you with a wrapper outline for what you want. It will probably help you visualize the information above, but it may not be entirely correct. Let me know if something needs fixing.

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

Since there is no default constructor for a struct you will probably want to provide a free function that returns this structure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文