tc39 / proposal-structs

JavaScript Structs: Fixed Layout Objects
http://tc39.es/proposal-structs/
622 stars 11 forks source link

Atomics, shared struct fields, and references #6

Open rbuckton opened 3 years ago

rbuckton commented 3 years ago

In the slides there's an example of a possible future API for using shared structs with Atomics. I had been considering the same thing with https://github.com/rbuckton/proposal-struct and https://github.com/rbuckton/proposal-refs. The examples in the slides are as follows:

Atomics.store(sharedBox, 'x', 42);
Atomics.load(sharedBox, 'x');
Atomics.exchange(sharedBox, 'x', 84);
Atomics.compareExchange(sharedBox, 'x', 84, 42);

The approach I had been considering would have used ref instead:

Atomics.store(ref sharedBox.x, 42);
Atomics.load(ref sharedBox.x);
Atomics.exchange(ref sharedBox.x, 84);
Atomics.compareExchange(ref sharedBox.x, 84, 42);

That said, its not necessary that we take a dependency on https://github.com/rbuckton/proposal-refs. Should that proposal be accepted once I've had the opportunity to present it, I had intended to introduce ref-style "overloads" for Atomics for typed arrays as well, i.e.: Atomics.store(ref int32Array[0], 42), so in essence both patterns could exist.

syg commented 3 years ago

Interesting, if refs existed, ref sharedBox.x is the more statically analyzable form, so that seems pretty nice.

My initial thought was exactly "both overloads seem fine". Given that, I strongly prefer no dependence on refs, but instead this proposal giving another (edit: maybe not another since you were already considering, but reinforcing) motivating use case for the refs proposal.

rbuckton commented 3 years ago

If we ever plan to support private fields in shared structs (which won't be useful unless we have shared functions), we'll probably need ref since you can't use the private name as a key:

shared struct class Data {
  #value = 1;

  foo() {
    return Atomics.compareExchange(ref this.#value, 1, 2)
  }
}

I wrote up a more detailed (and possibly buggy) example of this (along with a sketch of "shared modules" and "shared functions") here: https://gist.github.com/rbuckton/4bcf5ba532f594b5f9a076cb86c4a4e8

rbuckton commented 3 years ago

(which still doesn't gate this proposal on ref, but might gate private fields on something like ref)

rbuckton commented 3 years ago

I suppose its still feasible to avoid ref by storing the value indirectly:

shared struct class ValueHolder {
  value;
  constructor(value) { this.value = value; }
}
shared struct class Data {
  #value = new ValueHolder(1);
  foo() {
    return Atomics.compareExchange(this.#value, "value", 1, 2);
  }
}

At the cost of the extra memory needed.