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);
}
浙公网安备 33010602011771号