import '../../../assert/js/assert.js';
import '../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * Represents a storage-level array.
 *
 * We need to track which execution threads/invocations have written to which indices, so that we can (a) ensure that
 * we won't get data races (and will have uniform control flow), and (b) in the future potentially simulate cases where
 * we might get more undefined-like behavior between which values we get.
 *
 * For workgroup-level arrays, we only need to track the local invocation within that workgroup wrote to that index.
 *
 * TODO: for NOW, we'll lock out and fail on reads (if another thread wrote), OR multiple-thread writes, HOWEVER
 * TODO: we should make it possible to return arbitrary results (and track values) for other cases
 *
 * See ParallelExecutor for more high-level documentation.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { alpenglow } from '../imports.js';
export default class ParallelWorkgroupArray {
    constructor(data, indeterminateValue) {
        this.data = data;
        this.indeterminateValue = indeterminateValue;
        this.writeLocalIDs = data.map(() => []);
    }
    async get(context, index) {
        let value;
        if (!isFinite(index) || index < 0 || index >= this.data.length) {
            value = this.indeterminateValue;
        }
        else {
            // Ensure that we're the only ones who have written to this
            assert && assert(this.writeLocalIDs[index].every(id => id.equals(context.localId)));
            value = this.data[index];
        }
        await context.afterGet();
        return value;
    }
    async set(context, index, value) {
        if (isFinite(index) && index >= 0 && index < this.data.length) {
            // Ensure that we're the only ones who have written to this
            assert && assert(this.writeLocalIDs[index].every(id => id.equals(context.localId)));
            this.writeLocalIDs[index].push(context.localId);
            this.data[index] = value;
        }
        await context.afterSet();
    }
    synchronize(workgroupId) {
        // TODO: assert that we're in the same workgroup?
        // Clear IDs that were written
        this.writeLocalIDs.forEach(ids => {
            ids.length = 0;
        });
    }
}
alpenglow.register('ParallelWorkgroupArray', ParallelWorkgroupArray);
//# sourceMappingURL=ParallelWorkgroupArray.js.map