Open bradcray opened 1 hour ago
For my tastes, I'd implement atomic fields in the near-term because it seems tractable, logical, and useful. The sync case requires more work, and doesn't seem quite as important to me, but would be nice to nail down eventually, particularly if it led us to introduce the ability to reason about whether the user passed an argument or relied upon its default value.
In https://github.com/Cray/chapel-private/issues/6871, it was noted that
on someLocale var i: atomic int;
doesn't currently work, where the reason is that we don't currently support compiler-generated default initializers for sync/atomic fields. That led me to refresh my memory about why we disallowed them, where I want to capture the notion that we should consider re-enabling support foratomic
fields, and possibly forsync
as well.Reviewing the reasons for disallowing compiler-generated default initializers for these fields, I think there are two:
First reason
The first applies to
sync
andatomic
fields, which is that in general for a field of type t:we generate an initializer that optionally takes an argument of type
t
as its type:However, for sync/atomic fields, this means that we'd take in a
sync
oratomic
actual type and would have to apply a method to read it, e.g.:I think the approach we should take here is to define the compiler-generated initializer arguments for
sync t
andatomic t
fields simply be of typet
since this is generally how such variables are initialized anyway (e.g.,var x: atomic int = 1, y: atomic int = 2;
). More to the point, we don't really support initializing a sync from another sync in user code (though we do for atomics, presumably for convenience and because there's no ambiguity as to the result?).In this scheme, the initializer for the R2 record above would be:
Second reason
The second reason is pretty specific to sync fields, and that is that we'd probably want to distinguish between whether the field should be initialized to be full or empty, potentially by distinguishing between the cases where a user passed in a value vs. didn't somehow. That is, given:
s
will be initialized to be full, whiles2
will be initialized to be empty. So presumably for a case like:we might expect the behavior of the following cases to be as indicated in the comments:
Yet, to get this behavior, we'd either need to create multiple overloads of the initializer (2**(# of sync fields?)) or else introduce the ability to distinguish within Chapel code whether an argument got its value from its default value or used a user-supplied one (something that we, and users, have wanted anyway).
So this case also seems tractable, simply more work. Specifically, imagine something that logically worked like: