| 382 | ) |
| 383 | |
| 384 | const release = <K, A, E>(self: RcMap<K, A, E>, key: K, entry: State.Entry<A, E>) => |
| 385 | Effect.withFiber((fiber) => { |
| 386 | entry.refCount-- |
| 387 | if (entry.refCount > 0) { |
| 388 | return Effect.void |
| 389 | } else if ( |
| 390 | self.state._tag === "Closed" |
| 391 | || !MutableHashMap.has(self.state.map, key) |
| 392 | || Duration.isZero(entry.idleTimeToLive) |
| 393 | ) { |
| 394 | if (self.state._tag === "Open") { |
| 395 | MutableHashMap.remove(self.state.map, key) |
| 396 | } |
| 397 | return Scope.close(entry.scope, Exit.void) |
| 398 | } else if (!Duration.isFinite(entry.idleTimeToLive)) { |
| 399 | return Effect.void |
| 400 | } |
| 401 | |
| 402 | const clock = fiber.getRef(Clock) |
| 403 | entry.expiresAt = clock.currentTimeMillisUnsafe() + Duration.toMillis(entry.idleTimeToLive) |
| 404 | if (entry.fiber) return Effect.void |
| 405 | |
| 406 | entry.fiber = Effect.interruptibleMask(function loop(restore): Effect.Effect<void> { |
| 407 | const now = clock.currentTimeMillisUnsafe() |
| 408 | const remaining = entry.expiresAt - now |
| 409 | if (remaining <= 0) { |
| 410 | if (self.state._tag === "Closed" || entry.refCount > 0) return Effect.void |
| 411 | MutableHashMap.remove(self.state.map, key) |
| 412 | return restore(Scope.close(entry.scope, Exit.void)) |
| 413 | } |
| 414 | return Effect.flatMap(clock.sleep(Duration.millis(remaining)), () => loop(restore)) |
| 415 | }).pipe( |
| 416 | Effect.ensuring(Effect.sync(() => { |
| 417 | entry.fiber = undefined |
| 418 | })), |
| 419 | Effect.runForkWith(fiber.context), |
| 420 | Fiber.runIn(self.scope) |
| 421 | ) |
| 422 | return Effect.void |
| 423 | }) |
| 424 | |
| 425 | /** |
| 426 | * Returns an iterable of all keys currently stored in the `RcMap`. |