d的线安弱引用实现

原文

import core.atomic,core.memory;

private alias void delegate(Object) DEvent;
private extern (C) void rt_attachDisposeEvent(Object h, DEvent e);
private extern (C) void rt_detachDisposeEvent(Object h, DEvent e);

final class Weak(T : Object)
{
    private size_t _object;
    private size_t _ptr;
    private hash_t _hash;

    this(T object)
    in
    {
        assert(object);
    }
//用保守垃集技巧.不适用`压缩/复制`.如`D`添加`压缩`,则用`内置`弱引用.
    do
    {
        //动 ptr=cast(size_t)cast(void*)object;
        auto ptr = cast(size_t)*(cast(void**)&obj);

        // 使用原子,因为并非所有架构都可保证这些值的原子存储和加载
        atomicStore(*cast(shared)&_object, ptr);

        // 只赋值一次,所以没有原子
        _ptr = ptr;
        _hash = typeid(T).getHash(&object);

        rt_attachDisposeEvent(object, &unhook);
        GC.setAttr(cast(void*)this, GC.BlkAttr.NO_SCAN);
    }

    @property T object()
    {
        auto obj = cast(T)cast(void*)atomicLoad(*cast(shared)&_object);

    // 移动对象,至垃集堆,因而,可查询是否活着.
    //注意,即使`objlocal`的强制转换和赋值
    //未把对象放入栈,此调用也会.
    //所以,这是安全的
        if (GC.addrOf(cast(void*)obj))return obj;

        return null;
    }

    private void unhook(Object object)
    {
        rt_detachDisposeEvent(object, &unhook);

        //该赋值很重要.
       //如果收集时,不置`mObject`为空,则`垃集`为新对象`重用`内存时,对象中的检查,可能返回`假阳`性.
        atomicStore(*cast(shared)&_object, cast(size_t)0);
    }

    override equals_t opEquals(Object o)
    {
        if (this is o)return true;

        if (auto weak = cast(Weak!T)o)
            return _ptr == weak._ptr;

        return false;
    }

    override int opCmp(Object o)
    {
        if (auto weak = cast(Weak!T)o)
            return _ptr > weak._ptr;

        return 1;
    }

    override hash_t toHash()
    {
        auto obj = object;

        return obj ? typeid(T).getHash(&obj) : _hash;
    }

    override string toString()
    {
        auto obj = object;

        return obj?obj.toString():toString();
    }
}

注意:
1,为简单起见,我搞成类.不值得变成,因为弱引用已经暗示了垃集.
2,实现依赖atomicLoad/atomicStore来,在x86上使用实际加锁前缀指令(及其他架构上的等效指令),而不是如自旋锁.
3,显然不适合压缩GC.理想情况下,压缩垃集全面支持弱(或软)引用,因此不必侵改.但是,在那之前,恕我直言,这是标准库的必要补充.
4,该类不支持存储对象上的自定义重载,opEquals()opCmp();它总是等价的用引用.还在构建时存储哈希值.这是必要的,因为Weak(T)不能按AA键使用,因为需要调用容器对象(会被垃集)上方法时,无法维护不变量.
5,严格来说,在x86原子不是必需的,因为一切都是size_t,并且加载/存储他们同样保证是原子的.但是,为了安全,我选择了用原子来匹配非x86架构.
5,我知道,我未用类型或方法限定符来注解.现在更专注实现.
6,黑客,黑客,黑客.我知道这并不漂亮,但除此外,无好方法来用保守的垃集线程安全方式来实现它.

auto ptr = cast(size_t)*cast(void**)&object;

对象可能有opCast方法,如上避免意外调用它.

posted @   zjh6  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示