| 132 | export const makeSemaphore = (permits: number) => core.sync(() => unsafeMakeSemaphore(permits)) |
| 133 | |
| 134 | class Latch extends Effectable.Class<void> implements Effect.Latch { |
| 135 | waiters: Array<(_: Effect.Effect<void>) => void> = [] |
| 136 | scheduled = false |
| 137 | constructor(private isOpen: boolean) { |
| 138 | super() |
| 139 | } |
| 140 | |
| 141 | commit() { |
| 142 | return this.await |
| 143 | } |
| 144 | |
| 145 | private unsafeSchedule(fiber: Fiber.RuntimeFiber<void>) { |
| 146 | if (this.scheduled || this.waiters.length === 0) { |
| 147 | return core.void |
| 148 | } |
| 149 | this.scheduled = true |
| 150 | fiber.currentScheduler.scheduleTask(this.flushWaiters, fiber.getFiberRef(core.currentSchedulingPriority), fiber) |
| 151 | return core.void |
| 152 | } |
| 153 | private flushWaiters = () => { |
| 154 | this.scheduled = false |
| 155 | const waiters = this.waiters |
| 156 | this.waiters = [] |
| 157 | for (let i = 0; i < waiters.length; i++) { |
| 158 | waiters[i](core.exitVoid) |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | open = core.withFiberRuntime<void>((fiber) => { |
| 163 | if (this.isOpen) { |
| 164 | return core.void |
| 165 | } |
| 166 | this.isOpen = true |
| 167 | return this.unsafeSchedule(fiber) |
| 168 | }) |
| 169 | unsafeOpen() { |
| 170 | if (this.isOpen) return |
| 171 | this.isOpen = true |
| 172 | this.flushWaiters() |
| 173 | } |
| 174 | release = core.withFiberRuntime<void>((fiber) => { |
| 175 | if (this.isOpen) { |
| 176 | return core.void |
| 177 | } |
| 178 | return this.unsafeSchedule(fiber) |
| 179 | }) |
| 180 | await = core.asyncInterrupt<void>((resume) => { |
| 181 | if (this.isOpen) { |
| 182 | return resume(core.void) |
| 183 | } |
| 184 | this.waiters.push(resume) |
| 185 | return core.sync(() => { |
| 186 | const index = this.waiters.indexOf(resume) |
| 187 | if (index !== -1) { |
| 188 | this.waiters.splice(index, 1) |
| 189 | } |
| 190 | }) |
| 191 | }) |
nothing calls this directly
no test coverage detected
searching dependent graphs…