d@nogc仍应允许分配合同串
void foo(string s) @safe pure nothrow @nogc
in (s != "hello", "Invalid " ~ s) {
}
void main() {}
错误:不能在@nogc
的deneme.foo
函数中使用~
符号.
但是该符号仅在即抛错误
时使用,即不应继续执行该程序
.所以,只分配一点GC
不会有什么坏处,对吧?
😅
否则,必须丢弃@nogc
注解或提供有用错误消息
功能.
如果GC
完全禁止甚至没有初化怎么办?是你想要使用@nogc
的环境.
如果完全禁止GC
(就像在BetterC
中一样),甚至不会首先编译"Invalid"~s
表达式.因此,需要其他方式创建
错误消息(可能使用malloc
)
避免GC
的主要动机之一是防止低延迟
代码遭受GC
的"停止世界"
的暂停.
通过在函数
级别而不是整个程序
级别操作,@nogc
可帮助编写
正确程序,其中可承受延迟
代码可用GC
,而低延迟
代码可在单独
线程中运行来避免它,这些线程
在收集
时不会停止.简单从程序
中完全删除GC
会强制所有内容
而不仅是延迟敏感
部分,都变为@nogc
.
(话虽如此,@nogc
仍是非常不完整和不安全
的方法,因为它没有阻止
程序中使用GC
的部分,通过参数或共享内存传递GC
内存的所有权
给@nogc
线程,也没有阻止使用有GC
依赖的模块,线本
构造器的模块.)
@nogc
在合同中仍应允许分配
串.
诀窍是,不是在那儿立即创建错误串
,而是抛包含一些数据的错误
.稍后在使用错误
数据时使用GC
.如果data
有需要GC
的复制构造器
,那么祝你好运.:p
工作原理
:
程序员使用区分串
定义错误.SumType
定义必须列举
此类错误可携带的所有类型数据
.(幸好,编译时
错误会告诉你缺少需要添加
的元组类型.)
mixin NoGcError!("Foo", SumType!(Tuple!(Foo, int, int), Tuple!(string), Tuple!()));
尽管"Foo"
可以是任何东西,但同结构
关联是有意义
的:
struct Foo {
int i;
用户在生成
错误串时必须指定"Foo"
:
void bar(int i, int j) @safe pure nothrow @nogc
in (i == 42, error!"Foo"("一些错误", this, i, j)) {
// ...
}
注意此处不同类型
的错误数据:
void zar(string str, double d) @safe pure nothrow @nogc
in (!isNaN(d), error!"Foo"("不能为Nan", str)) {
// ...
}
}
error!"Foo"
也可以用来抛
合约外内容.
void main() {
auto f = Foo(1);
// f.bar(42, 44);
// f.zar("hello world", double.init);
error!"Foo"("错误!");
}
完整草稿:
import std; // Sorry :(
mixin NoGcError!("Foo",SumType!(Tuple!(Foo,int,int),Tuple!(string),Tuple!()));
struct Foo {
int i;
void bar(int i, int j) @safe pure nothrow @nogc
in (i == 42, error!"Foo"("一些错", this, i, j)) {
// ...
}
void zar(string str, double d) @safe pure nothrow @nogc
in (!isNaN(d), error!"Foo"("不能为nan", str)) {
// ...
}
}
void main() {
auto f = Foo(1);
// f.bar(42, 44);
// f.zar("hello world", double.init);
error!"Foo"("错误!");
}
mixin template NoGcError(string tag, Data) {
class NoGcError : Error {
string msg;
Data data;
enum noDataString = Tuple!()().to!string;
this() {
super(tag ~ " Error");
}
// 从object.Throwable.toString适配
override
void toString(scope void delegate(in char[]) sink) const {
sink(file); sink(":"); sink(line.to!string); sink(": ");
sink(tag); sink(" Error: "); sink(msg);
const dataStr = data.to!string;
if (dataStr != noDataString) {
sink("\n 数据: "); sink(dataStr);
}
if (info) {
try {
sink("\n----------------");
foreach (t; info) {
sink("\n"); sink(t);
}
} catch (Throwable) {
// 忽略更多错误
}
}
}
}
static ref error_(string t)()
if (t == tag) {
static NoGcError err_;
return err_;
}
static this() {
error_!tag = new NoGcError();
}
}
string error(string tag, Data...)(string msg, Data data, string file = __FILE__, size_t line = __LINE__) @safe pure nothrow @nogc {
static auto thrower(string msg, Data data, string file, size_t line) @trusted nothrow @nogc {
static assert (__traits(compiles, error_!tag.data = tuple(data)),format!`NoGcError的和类型!"%s"必须包括Tuple!%s`(tag, Data.stringof));
error_!tag.msg = msg;
error_!tag.data = tuple(data);
error_!tag.file = file;
error_!tag.line = line;
throw error_!tag;
}
// 从std/regex/internal/ir.d适配
static assumePureFunction(T)(T t) @trusted pure nothrow @nogc {
enum attrs = functionAttributes!T | FunctionAttribute.pure_;
return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
}
assumePureFunction(&thrower)(msg, data, file, line);
assert(false);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现