const fileName_1 = "(@effect/core) _src/io/Effect/operations/interruption.ts";
import * as tsplus_module_1 from "@effect/core/io/Effect/operations/suspendSucceed";
import * as tsplus_module_2 from "@effect/core/io/Effect/operations/fiberId";
import * as tsplus_module_3 from "@effect/core/io/Effect/operations/flatMap";
import * as tsplus_module_4 from "@effect/core/io/InterruptStatus/definition";
import * as tsplus_module_5 from "@effect/core/io/Fiber/operations/interruptAs";
import * as tsplus_module_6 from "@effect/core/io/Effect/operations/forkDaemon";
import * as tsplus_module_7 from "@effect/core/io/Fiber/operations/join";
import * as tsplus_module_8 from "@effect/core/io/Cause/operations/isInterrupted";
import * as tsplus_module_9 from "@effect/core/io/Cause/operations/interruptors";
import * as tsplus_module_10 from "@effect/core/io/Effect/operations/failCauseNow";
import * as tsplus_module_11 from "@effect/core/io/Effect/operations/zipRight";
import * as tsplus_module_12 from "@effect/core/io/Effect/operations/succeedNow";
import * as tsplus_module_13 from "@effect/core/io/Effect/operations/foldCauseEffect";
import * as tsplus_module_14 from "@effect/core/io/Cause/definition";
import * as tsplus_module_15 from "@effect/core/io/Effect/operations/failCause";
export const interruptStatus_ = interruptStatus_1;
export const interruptible = interruptible_1;
export const uninterruptible = uninterruptible_1;
export const checkInterruptible = checkInterruptible_1;
export const uninterruptibleMask = uninterruptibleMask_1;
export const disconnect = disconnect_1;
export const onInterrupt_ = onInterrupt_1;
export const interruptAs = interruptAs_1;
import { ICheckInterrupt, IInterruptStatus } from "@effect/core/io/Effect/definition/primitives";
export class InterruptStatusRestoreImpl {
  constructor(flag) {
    this.flag = flag;

    this.restore = (effect, __tsplusTrace) => {
      return tsplus_module_1.suspendSucceed(() => interruptStatus_1(effect(), () => this.flag, fileName_1 + ":34:58"), fileName_1 + ":34:33");
    };

    this.force = (effect, __tsplusTrace) => {
      return tsplus_module_1.suspendSucceed(() => this.flag.isUninterruptible ? interruptible_1(disconnect_1(uninterruptible_1(effect(), fileName_1 + ":43:35"), fileName_1 + ":43:48"), fileName_1 + ":43:64") : interruptStatus_1(effect(), () => this.flag, fileName_1 + ":44:35"), fileName_1 + ":41:33");
    };
  }

} // -----------------------------------------------------------------------------
// Operations
// -----------------------------------------------------------------------------

/**
 * Returns an effect that is interrupted by the current fiber
 *
 * @tsplus static ets/Effect/Ops interrupt
 */

export const interrupt = /*#__PURE__*/tsplus_module_3.flatMap_(tsplus_module_2.fiberId, fiberId => interruptAs_1(() => fiberId, fileName_1 + ":58:80"), fileName_1 + ":58:48");
/**
 * Switches the interrupt status for this effect. If `true` is used, then the
 * effect becomes interruptible (the default), while if `false` is used, then
 * the effect becomes uninterruptible. These changes are compositional, so
 * they only affect regions of the effect.
 *
 * @tsplus fluent ets/Effect interruptStatus
 */

function interruptStatus_1(self, flag, __tsplusTrace) {
  return new IInterruptStatus(self, flag, __tsplusTrace);
}
/**
 * Switches the interrupt status for this effect. If `true` is used, then the
 * effect becomes interruptible (the default), while if `false` is used, then
 * the effect becomes uninterruptible. These changes are compositional, so
 * they only affect regions of the effect.
 *
 * @tsplus static ets/Effect/Aspects interruptStatus
 */


export const interruptStatus = (flag, __tsplusTrace) => self => interruptStatus_(self, flag, __tsplusTrace);
/**
 * Returns a new effect that performs the same operations as this effect, but
 * interruptibly, even if composed inside of an uninterruptible region.
 *
 * Note that effects are interruptible by default, so this function only has
 * meaning if used within an uninterruptible region.
 *
 * **WARNING**: This operator "punches holes" into effects, allowing them to be
 * interrupted in unexpected places. Do not use this operator unless you know
 * exactly what you are doing. Instead, you should use `uninterruptibleMask`.
 *
 * @tsplus fluent ets/Effect interruptible
 */

function interruptible_1(self, __tsplusTrace) {
  return interruptStatus_1(self, () => tsplus_module_4.Interruptible, __tsplusTrace);
}
/**
 * Performs this effect uninterruptibly. This will prevent the effect from
 * being terminated externally, but the effect may fail for internal reasons
 * (e.g. an uncaught error) or terminate due to defect.
 *
 * Uninterruptible effects may recover from all failure causes (including
 * interruption of an inner effect that has been made interruptible).
 *
 * @tsplus fluent ets/Effect uninterruptible
 */


function uninterruptible_1(self, __tsplusTrace) {
  return interruptStatus_1(self, () => tsplus_module_4.Uninterruptible, __tsplusTrace);
}
/**
 * Checks the interrupt status, and produces the effect returned by the
 * specified callback.
 *
 * @tsplus static ets/Effect/Ops checkInterruptible
 */


function checkInterruptible_1(f, __tsplusTrace) {
  return new ICheckInterrupt(f, __tsplusTrace);
}
/**
 * Makes the effect interruptible, but passes it a restore function that can
 * be used to restore the inherited interruptibility from whatever region the
 * effect is composed into.
 *
 * @tsplus static ets/Effect/Ops interruptibleMask
 */


export function interruptibleMask(f, __tsplusTrace) {
  return checkInterruptible_1(flag => interruptible_1(f(new InterruptStatusRestoreImpl(flag)), __tsplusTrace), __tsplusTrace);
}
/**
 * Makes the effect uninterruptible, but passes it a restore function that can
 * be used to restore the inherited interruptibility from whatever region the
 * effect is composed into.
 *
 * @tsplus static ets/Effect/Ops uninterruptibleMask
 */

function uninterruptibleMask_1(f, __tsplusTrace) {
  return checkInterruptible_1(flag => uninterruptible_1(f(new InterruptStatusRestoreImpl(flag)), __tsplusTrace), __tsplusTrace);
}
/**
 * Returns an effect whose interruption will be disconnected from the
 * fiber's own interruption, being performed in the background without
 * slowing down the fiber's interruption.
 *
 * This method is useful to create "fast interrupting" effects. For
 * example, if you call this on a bracketed effect, then even if the
 * effect is "stuck" in acquire or release, its interruption will return
 * immediately, while the acquire / release are performed in the
 * background.
 *
 * See timeout and race for other applications.
 *
 * @tsplus fluent ets/Effect disconnect
 */


function disconnect_1(effect, __tsplusTrace) {
  return uninterruptibleMask_1(({
    restore
  }) => tsplus_module_3.flatMap_(tsplus_module_2.fiberId, id => tsplus_module_3.flatMap_(tsplus_module_6.forkDaemon(restore(() => effect, __tsplusTrace), __tsplusTrace), fiber => onInterrupt_1(restore(() => tsplus_module_7.join(fiber, __tsplusTrace), __tsplusTrace), () => tsplus_module_6.forkDaemon(tsplus_module_5.interruptAsNow_(fiber, id, __tsplusTrace), __tsplusTrace), __tsplusTrace), __tsplusTrace), __tsplusTrace), __tsplusTrace);
}
/**
 * Calls the specified function, and runs the effect it returns, if this
 * effect is interrupted.
 *
 * @tsplus fluent ets/Effect onInterrupt
 */


function onInterrupt_1(self, cleanup, __tsplusTrace) {
  return uninterruptibleMask_1(({
    restore
  }) => tsplus_module_13.foldCauseEffect_(restore(() => self, __tsplusTrace), cause => tsplus_module_8.isInterrupted(cause) ? tsplus_module_11.zipRight_(cleanup(tsplus_module_9.interruptors(cause)), () => tsplus_module_10.failCauseNow(cause, __tsplusTrace), __tsplusTrace) : tsplus_module_10.failCauseNow(cause, __tsplusTrace), tsplus_module_12.succeedNow, __tsplusTrace), __tsplusTrace);
}
/**
 * Calls the specified function, and runs the effect it returns, if this
 * effect is interrupted.
 *
 * @tsplus static ets/Effect/Aspects onInterrupt
 */


export const onInterrupt = (cleanup, __tsplusTrace) => self => onInterrupt_(self, cleanup, __tsplusTrace);
/**
 * Calls the specified function, and runs the effect it returns, if this
 * effect is interrupted (allows for expanding error).
 *
 * @tsplus fluent ets/Effect onInterruptPolymorphic
 */

export function onInterruptPolymorphic_(self, cleanup, __tsplusTrace) {
  return uninterruptibleMask_1(({
    restore
  }) => tsplus_module_13.foldCauseEffect_(restore(() => self, __tsplusTrace), cause => tsplus_module_8.isInterrupted(cause) ? tsplus_module_13.foldCauseEffect_(cleanup(tsplus_module_9.interruptors(cause)), _ => tsplus_module_10.failCauseNow(_, __tsplusTrace), () => tsplus_module_10.failCauseNow(cause, __tsplusTrace), __tsplusTrace) : tsplus_module_10.failCauseNow(cause, __tsplusTrace), tsplus_module_12.succeedNow, __tsplusTrace), __tsplusTrace);
}
/**
 * Calls the specified function, and runs the effect it returns, if this
 * effect is interrupted (allows for expanding error).
 *
 * @tsplus static ets/Effect/Aspects onInterruptPolymorphic
 */

export const onInterruptPolymorphic = (cleanup, __tsplusTrace) => self => onInterruptPolymorphic_(self, cleanup, __tsplusTrace);
/**
 * Returns an effect that is interrupted as if by the specified fiber.
 *
 * @tsplus static ets/Effect/Ops interruptAs
 */

function interruptAs_1(fiberId, __tsplusTrace) {
  return tsplus_module_15.failCause(() => tsplus_module_14.interrupt(fiberId()), __tsplusTrace);
}
//# sourceMappingURL=interruption.mjs.map