去年,解决问题的方法是使我的实例变量原子化,以确保其他任务可以看到它们的更改。 (While loop in a method gets stuck. Adding an assignment of a field to itself fixes the issue)
今年,我将用构造器替换构造函数。 (https://chapel-lang.org/docs/master/language/evolution.html#readme-evolution-initializers-replace-constructors)不幸的是,我不知道如何初始化原子实例变量。该代码不起作用:
class FakeSemaphore {
var tokens : atomic int;
proc init(initTokens : int) {
this.tokens.write(initTokens);
}
}
这将在教堂1.18中产生以下结果:
$ chpl FakeSemaphore.chpl
FakeSemaphore.chpl:4: In initializer:
FakeSemaphore.chpl:5: error: field "tokens" used before it is initialized
我应该如何初始化原子实例变量?
答案 0 :(得分:4)
简短的答案是,应在致电this.complete()
之前插入对this.tokens.write()
的呼叫,如下所示(Try It Online):
class FakeSemaphore {
var tokens : atomic int;
proc init(initTokens : int) {
this.complete();
this.tokens.write(initTokens);
}
}
var s = new owned FakeSemaphore(10);
writeln(s);
详细信息:
可以将教堂初始设定项视为具有多个阶段。最初,没有任何字段被初始化,对象及其字段只有在被初始化后才能使用。字段可以通过赋值运算符(=
)显式初始化,也可以由编译器隐式初始化。
内置调用this.complete()
用于指示该对象已被初始化并可以使用。遇到该错误时,编译器将负责初始化用户未剩余的所有剩余字段。调用this.complete()
之后,就可以使用该对象了。
在这种情况下,即使您在逻辑上使用方法调用this.tokens.write(initTokens)
来初始化this.tokens
,Chapel也不会将其识别为字段初始化,因为它没有使用赋值运算符。而且,由于这是对字段的方法调用,因此仅在对象初始化后(即在调用this.complete()
之后)才被允许。
请注意,Chapel有长期的意图(在我们的GitHub问题页面上的issue #5037中捕获)支持原子变量的直接初始化。一旦支持,您应该可以编写:
class FakeSemaphore {
var tokens : atomic int;
proc init(initTokens: int) {
this.tokens = initTokens;
}
}
我希望此功能在2019年可用。还要注意一个相关要求,即能够直接分配原子变量,而不是被迫在issue #8847中使用.write()