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
方法,如上避免意外调用
它.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现