(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A, E>)
| 193 | }) |
| 194 | |
| 195 | const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A, E>) => |
| 196 | coreEffect.clockWith((clock) => { |
| 197 | entry.refCount-- |
| 198 | if (entry.refCount > 0) { |
| 199 | return core.void |
| 200 | } else if ( |
| 201 | self.state._tag === "Closed" |
| 202 | || !MutableHashMap.has(self.state.map, key) |
| 203 | || Duration.isZero(entry.idleTimeToLive) |
| 204 | ) { |
| 205 | if (self.state._tag === "Open") { |
| 206 | MutableHashMap.remove(self.state.map, key) |
| 207 | } |
| 208 | return core.scopeClose(entry.scope, core.exitVoid) |
| 209 | } |
| 210 | |
| 211 | if (!Duration.isFinite(entry.idleTimeToLive)) { |
| 212 | return core.void |
| 213 | } |
| 214 | |
| 215 | entry.expiresAt = clock.unsafeCurrentTimeMillis() + Duration.toMillis(entry.idleTimeToLive) |
| 216 | if (entry.fiber) return core.void |
| 217 | |
| 218 | return core.interruptibleMask(function loop(restore): Effect<void> { |
| 219 | const now = clock.unsafeCurrentTimeMillis() |
| 220 | const remaining = entry.expiresAt - now |
| 221 | if (remaining <= 0) { |
| 222 | if (self.state._tag === "Closed" || entry.refCount > 0) return core.void |
| 223 | MutableHashMap.remove(self.state.map, key) |
| 224 | return restore(core.scopeClose(entry.scope, core.exitVoid)) |
| 225 | } |
| 226 | return core.flatMap(clock.sleep(Duration.millis(remaining)), () => loop(restore)) |
| 227 | }).pipe( |
| 228 | fiberRuntime.ensuring(core.sync(() => { |
| 229 | entry.fiber = undefined |
| 230 | })), |
| 231 | circular.forkIn(self.scope), |
| 232 | core.tap((fiber) => { |
| 233 | entry.fiber = fiber |
| 234 | }), |
| 235 | self.semaphore.withPermits(1) |
| 236 | ) |
| 237 | }) |
| 238 | |
| 239 | /** @internal */ |
| 240 | export const keys = <K, A, E>(self: RcMap.RcMap<K, A, E>): Effect<Array<K>> => { |
no test coverage detected