UNPKG

@effect-ts/system

Version:

Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.

197 lines (152 loc) 4.85 kB
// ets_tracing: off import "../../Operator/index.js" import * as Chunk from "../../Collections/Immutable/Chunk/index.js" import type { MutableArray } from "../../Support/Mutable/index.js" import { Hub, Subscription } from "./Hub.js" export class BoundedHubPow2<A> extends Hub<A> { array: MutableArray<A> mask: number publisherIndex = 0 subscribers: MutableArray<number> subscriberCount = 0 subscribersIndex = 0 readonly capacity: number constructor(requestedCapacity: number) { super() this.array = Array.from({ length: requestedCapacity }) this.mask = requestedCapacity = 1 this.subscribers = Array.from({ length: requestedCapacity }) this.capacity = requestedCapacity } isEmpty(): boolean { return this.publisherIndex === this.subscribersIndex } isFull(): boolean { return this.publisherIndex === this.subscribersIndex + this.capacity } publish(a: A): boolean { if (this.isFull()) { return false } if (this.subscriberCount !== 0) { const index = this.publisherIndex & this.mask this.array[index] = a this.subscribers[index] = this.subscriberCount this.publisherIndex += 1 } return true } publishAll(as: Iterable<A>): Chunk.Chunk<A> { const asArray = Chunk.from(as) const n = Chunk.size(asArray) const size = this.publisherIndex - this.subscribersIndex const available = this.capacity - size const forHub = Math.min(n, available) if (forHub === 0) { return asArray } let iteratorIndex = 0 const publishAllIndex = this.publisherIndex + forHub while (this.publisherIndex !== publishAllIndex) { const a = asArray[iteratorIndex++]! const index = this.publisherIndex & this.mask this.array[index] = a this.publisherIndex += 1 } return Chunk.drop_(asArray, iteratorIndex - 1) } size(): number { return this.publisherIndex - this.subscribersIndex } slide(): void { if (this.subscribersIndex !== this.publisherIndex) { const index = this.subscribersIndex & this.mask this.array[index] = null as unknown as A this.subscribers[index] = 0 this.subscribersIndex += 1 } } subscribe(): Subscription<A> { this.subscriberCount += 1 return new BoundedHubPow2Subcription(this, this.publisherIndex, false) } } class BoundedHubPow2Subcription<A> extends Subscription<A> { constructor( private self: BoundedHubPow2<A>, private subscriberIndex: number, private unsubscribed: boolean ) { super() } isEmpty(): boolean { return ( this.unsubscribed || this.self.publisherIndex === this.subscriberIndex || this.self.publisherIndex === this.self.subscribersIndex ) } poll<D>(default_: D): A | D { if (this.unsubscribed) { return default_ } this.subscriberIndex = Math.max(this.subscriberIndex, this.self.subscribersIndex) if (this.subscriberIndex !== this.self.publisherIndex) { const index = this.subscriberIndex & this.self.mask const a = this.self.array[index]! this.self.subscribers[index] -= 1 if (this.self.subscribers[index] === 0) { this.self.array[index] = null as unknown as A this.self.subscribersIndex += 1 } this.subscriberIndex += 1 return a } return default_ } pollUpTo(n: number): Chunk.Chunk<A> { if (this.unsubscribed) { return Chunk.empty() } this.subscriberIndex = Math.max(this.subscriberIndex, this.self.subscribersIndex) const size = this.self.publisherIndex - this.subscriberIndex const toPoll = Math.min(n, size) if (toPoll <= 0) { return Chunk.empty() } let builder = Chunk.empty<A>() const pollUpToIndex = this.subscriberIndex + toPoll while (this.subscriberIndex !== pollUpToIndex) { const index = this.subscriberIndex & this.self.mask const a = this.self.array[index] as A builder = Chunk.append_(builder, a) this.subscriberIndex += 1 } return builder } size() { if (this.unsubscribed) { return 0 } return ( this.self.publisherIndex - Math.max(this.subscriberIndex, this.self.subscribersIndex) ) } unsubscribe(): void { if (!this.unsubscribed) { this.unsubscribed = true this.self.subscriberCount -= 1 this.subscriberIndex = Math.max(this.subscriberIndex, this.self.subscribersIndex) while (this.subscriberIndex < this.self.publisherIndex) { const index = this.subscriberIndex & this.self.mask this.self.subscribers[index] -= 1 if (this.self.subscribers[index] === 0) { this.self.array[index] = null as unknown as A this.self.subscribersIndex += 1 } this.subscriberIndex += 1 } } } }