Last year the solution to a problem was to make my instance variables atomics to ensure other tasks would see their changes. (While loop in a method gets stuck. Adding an assignment of a field to itself fixes the issue)
This year I'm replacing my constructors with initializers. (https://chapel-lang.org/docs/master/language/evolution.html#readme-evolution-initializers-replace-constructors) Unfortunately, I don't know how to initialize atomic instance variables. This code doesn't work:
class FakeSemaphore {
var tokens : atomic int;
proc init(initTokens : int) {
this.tokens.write(initTokens);
}
}
This results in the following in chapel 1.18:
$ chpl FakeSemaphore.chpl
FakeSemaphore.chpl:4: In initializer:
FakeSemaphore.chpl:5: error: field "tokens" used before it is initialized
How should I be initializing my atomic instance variables?
The short answer is that you should insert a call to this.complete()
prior to your call to this.tokens.write()
, as shown here (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);
In more detail:
Chapel initializers can be thought of as having multiple phases. Initially, none of the fields are initialized and the object and its fields cannot be used until they are. Fields can either be explicitly initialized via the assignment operator (=
) or implicitly initialized by the compiler.
The built-in call this.complete()
is used to indicate that the object has been initialized and is ready for use. Upon encountering it, the compiler will take care of initializing any remaining fields that the user did not. After the call to this.complete()
, the object is ready for use.
In this case, even though you're logically using the method call this.tokens.write(initTokens)
to initialize this.tokens
, Chapel doesn't recognize it as a field initialization since it isn't using the assignment operator. Moreover, since it's a method call on the field, it is only permitted once the object has been initialized (i.e., after the call to this.complete()
).
Note that Chapel has a long-standing intention (captured in issue #5037 on our GitHub issues page) to support direct initialization of atomic variables. Once this is supported, you should just be able to write:
class FakeSemaphore {
var tokens : atomic int;
proc init(initTokens: int) {
this.tokens = initTokens;
}
}
I expect this feature to become available in 2019. Also note a related request to be able to directly assign atomic variables rather than being forced to use .write()
in issue #8847
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With