All files / src/impl AtomicInteger.impl.ts

100% Statements 19/19
100% Branches 4/4
100% Functions 11/11
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                  25x 9x                           6x             4x             20x             10x             2x 2x             1x             2x             4x 4x   1x   1x   2x         9x       9x     9x 9x        
import { RequiredType } from "@jonloucks/contracts-ts/api/Types";
import { AtomicInteger } from "@jonloucks/contracts-ts/auxiliary/AtomicInteger";
 
/**
 * Factory to create an AtomicInteger implementation
 * 
 * @param initialValue the initial number value
 * @returns the new AtomicInteger implementation
 */
export function create(initialValue?: number): RequiredType<AtomicInteger> {
  return AtomicIntegerImpl.internalCreate(initialValue);
}
 
// ---- Implementation details below ----
 
/**
 * Implementation of AtomicInteger.
 */
class AtomicIntegerImpl implements AtomicInteger {
 
  /**
   * AtomicInteger.incrementAndGet override
   */
  incrementAndGet(): number {
    return Atomics.add(this.#array, 0, 1) + 1;
  }
 
  /** 
   * AtomicInteger.decrementAndGet override
   */
  decrementAndGet(): number {
    return Atomics.add(this.#array, 0, -1) - 1;
  }
 
  /**
   * AtomicInteger.get override
   */
  get(): number {
    return Atomics.load(this.#array, 0);
  }
 
  /** 
   * AtomicInteger.set override
   */
  set(value: number): void {
    Atomics.store(this.#array, 0, value);
  }
 
  /** 
   * AtomicInteger.compareAndSet override
   */
  compareAndSet(expectedValue: number, newValue: number): boolean {
    const current = Atomics.compareExchange(this.#array, 0, expectedValue, newValue);
    return current === expectedValue;
  }
 
  /**
   * AtomicInteger.getAndSet override
   */
  getAndSet(newValue: number): number {
    return Atomics.exchange(this.#array, 0, newValue);
  }
 
  /** 
   * Object.toString override
   */
  toString(): string {
    return this.get().toString();
  }
 
  /** 
   *  [Symbol.toPrimitive] override
   */
  [Symbol.toPrimitive](hint: string): string | number | boolean {
    const value: number = this.get();
    switch (hint) {
      case 'string':
        return value.toString();
      case 'boolean':
        return value !== 0;
      default:
        return value;
    }
  }
 
  static internalCreate(initialValue?: number): AtomicInteger {
    return new AtomicIntegerImpl(initialValue);
  }
 
  private constructor(initialValue: number = 0) {
    this.set(initialValue);
  }
 
  readonly #buffer: SharedArrayBuffer = new SharedArrayBuffer(4);
  readonly #array: Int32Array = new Int32Array(this.#buffer);
}