初始化教堂原子实例变量

时间:2019-01-30 23:04:48

标签: atomic chapel

去年,解决问题的方法是使我的实例变量原子化,以确保其他任务可以看到它们的更改。 (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

我应该如何初始化原子实例变量?

1 个答案:

答案 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()