import { Effect } from "@effect/core/io/Effect" import { _A, RefSym, SynchronizedSym } from "@effect/core/io/Ref/definition" import type { Maybe } from "@tsplus/stdlib/data/Maybe" export class SynchronizedInternal implements Ref.Synchronized { get [RefSym](): RefSym { return RefSym } get [SynchronizedSym](): SynchronizedSym { return SynchronizedSym } get [_A](): (_: never) => A { return (a) => a } constructor(readonly ref: Ref, readonly semaphore: TSemaphore) {} modifyEffect( this: this, f: (a: A) => Effect ): Effect { return this.semaphore.withPermit( this.get.flatMap(f).flatMap((tp) => { const [b, a] = tp return this.ref.set(a).as(b) }) ) } getAndUpdateEffect(this: this, f: (a: A) => Effect): Effect { return this.modifyEffect((v) => f(v).map((result) => [v, result] as const)) } getAndUpdateSomeEffect(this: this, pf: (a: A) => Maybe>): Effect { return this.modifyEffect(v => pf(v).getOrElse(Effect.succeed(v)).map((result) => [v, result] as const) ) } modifySomeEffect( this: this, fallback: B, pf: (a: A) => Maybe> ): Effect { return this.modifyEffect(v => pf(v).getOrElse(Effect.succeed([fallback, v] as const))) } updateEffect(this: this, f: (a: A) => Effect): Effect { return this.modifyEffect(v => f(v).map(result => [undefined as void, result] as const)) } updateAndGetEffect(this: this, f: (a: A) => Effect): Effect { return this.modifyEffect(v => f(v).map(result => [result, result] as const)) } updateSomeEffect(this: this, pf: (a: A) => Maybe>): Effect { return this.modifyEffect(v => pf(v).getOrElse(Effect.succeed(v)).map(result => [undefined as void, result] as const) ) } updateSomeAndGetEffect(this: this, pf: (a: A) => Maybe>): Effect { return this.modifyEffect(v => pf(v).getOrElse(Effect.succeed(v)).map(result => [result, result] as const) ) } get get(): Effect { return this.ref.get } modify(this: this, f: (a: A) => readonly [B, A]): Effect { return this.modifyEffect((a) => Effect.sync(f(a))) } set(this: this, a: A): Effect { return this.semaphore.withPermit(this.ref.set(a)) } getAndSet(this: this, a: A): Effect { return this.modify((v) => [v, a] as const) } getAndUpdate(this: this, f: (a: A) => A): Effect { return this.modify((v) => [v, f(v)] as const) } getAndUpdateSome( this: this, pf: (a: A) => Maybe ): Effect { return this.modify((v) => [v, pf(v).getOrElse(v)] as const) } modifySome( this: this, fallback: B, pf: (a: A) => Maybe ): Effect { return this.modify((v) => pf(v).getOrElse([fallback, v] as const)) } update(this: this, f: (a: A) => A): Effect { return this.modify((v) => [undefined as void, f(v)] as const) } updateAndGet(this: this, f: (a: A) => A): Effect { return this.modify(v => { const result = f(v) return [result, result] as const }) } updateSome( this: this, pf: (a: A) => Maybe ): Effect { return this.modify((v) => [undefined as void, pf(v).getOrElse(v)] as const) } updateSomeAndGet( this: this, pf: (a: A) => Maybe ): Effect { return this.modify(v => { const result = pf(v).getOrElse(v) return [result, result] as const }) } }