昨年の問題の解決策は、インスタンス変数をアトミックにして、他のタスクがそれらの変更を確認できるようにすることでした。(メソッドのwhileループがスタックします。それ自体にフィールドの割り当てを追加すると、問題が修正されます)
今年は、コンストラクターをイニシャライザーに置き換えます。(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
アトミックインスタンス変数をどのように初期化する必要がありますか?
簡単に言うthis.complete()
とthis.tokens.write()
、ここに示すように、への呼び出しの前にへの呼び出しを挿入する必要があります(オンラインで試す):
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の問題ページの問題#5037でキャプチャ)を持っていることに注意してください。これがサポートされると、次のように記述できるようになります。
class FakeSemaphore {
var tokens : atomic int;
proc init(initTokens: int) {
this.tokens = initTokens;
}
}
この機能は2019年に利用可能になる予定です。また.write()
、問題#8847で強制的に使用するのではなく、アトミック変数を直接割り当てることができるようにするための関連リクエストにも注意してください。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加