Skip to content
Effect Days 2026 Get your ticket

TxReentrantLock

Coordinates shared access inside transactions with read and write locks.

A TxReentrantLock lets many fibers hold read locks at the same time, or one fiber hold a write lock for exclusive access. Lock ownership is tracked by fiber, so a fiber that already holds the lock can acquire it again and later release each acquisition. Attempts that cannot proceed retry transactionally until the lock becomes available. This module includes manual, scoped, and wrapper-style operations for read and write locking.

17 exports Added in v2.0.0 Source

Constructors

make

Added in v2.0.0 Source

Creates a new TxReentrantLock.

Signature

declare function make(): Effect<TxReentrantLock>

Example

(Creating a reentrant lock)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.locked(lock)
})
await Effect.runPromise(program) // => false

Getters

locked

Added in v2.0.0 Source

Checks whether the lock is held by any fiber (read or write).

Signature

declare function locked(self: TxReentrantLock): Effect<boolean>

Example

(Checking whether a lock is held)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.locked(lock)
})
await Effect.runPromise(program) // => false

readLocked

Added in v2.0.0 Source

Checks whether any fiber holds a read lock.

Signature

declare function readLocked(self: TxReentrantLock): Effect<boolean>

Example

(Checking whether a read lock is held)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.readLocked(lock)
})
await Effect.runPromise(program) // => false

readLocks

Added in v2.0.0 Source

Returns the total number of read locks held across all fibers.

Signature

declare function readLocks(self: TxReentrantLock): Effect<number>

Example

(Counting read locks)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
yield* TxReentrantLock.acquireRead(lock)
const count = yield* TxReentrantLock.readLocks(lock)
yield* TxReentrantLock.releaseRead(lock)
return count
})
await Effect.runPromise(program) // => 1

writeLocked

Added in v2.0.0 Source

Checks whether any fiber holds a write lock.

Signature

declare function writeLocked(self: TxReentrantLock): Effect<boolean>

Example

(Checking whether a write lock is held)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.writeLocked(lock)
})
await Effect.runPromise(program) // => false

writeLocks

Added in v2.0.0 Source

Returns the number of write locks held (0 or the reentrant count).

Signature

declare function writeLocks(self: TxReentrantLock): Effect<number>

Example

(Counting write locks)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.writeLocks(lock)
})
await Effect.runPromise(program) // => 0

Guards

Checks whether the given value is a TxReentrantLock.

Signature

declare function isTxReentrantLock(u: unknown): u is TxReentrantLock

Example

(Checking for TxReentrantLock values)

import { TxReentrantLock } from "effect"
const someValue: unknown = {}
TxReentrantLock.isTxReentrantLock(someValue) // => false

Models

TxReentrantLock interface

Added in v4.0.0 Source

A TxReentrantLock provides a transactional read/write lock with reentrant semantics. Multiple readers can hold the lock concurrently, or a single writer can hold exclusive access. A fiber holding the write lock may acquire additional read/write locks (reentrancy).

Signature

interface TxReentrantLock extends Inspectable, Pipeable {
readonly "~effect/transactions/TxReentrantLock": "~effect/transactions/TxReentrantLock";
}

Example

(Using read and write locks)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
// Multiple readers can proceed concurrently
const read = yield* TxReentrantLock.withReadLock(lock, Effect.succeed("reading"))
// Writer gets exclusive access
const write = yield* TxReentrantLock.withWriteLock(lock, Effect.succeed("writing"))
return [read, write]
})
await Effect.runPromise(program) // => ["reading", "writing"]

Mutations

acquireRead

Added in v2.0.0 Source

Acquires a read lock. Blocks if another fiber holds the write lock. If the current fiber already holds the write lock, the read lock is granted (reentrancy). Returns the current number of read locks held by this fiber.

Signature

declare function acquireRead(self: TxReentrantLock): Effect<number>

Example

(Acquiring a read lock)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
const count = yield* TxReentrantLock.acquireRead(lock)
yield* TxReentrantLock.releaseRead(lock)
return count
})
await Effect.runPromise(program) // => 1

acquireWrite

Added in v2.0.0 Source

Acquires the write lock for the current fiber.

When to use

Use to enter an exclusive section manually when withWriteLock is not the right shape.

Details

Blocks if any other fiber holds a read or write lock. If the current fiber already holds the write lock, the count is incremented. If the current fiber holds a read lock, the write lock is granted as an upgrade.

Returns the current number of write locks held by this fiber.

Signature

declare function acquireWrite(self: TxReentrantLock): Effect<number>

Example

(Acquiring a write lock)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
const count = yield* TxReentrantLock.acquireWrite(lock)
yield* TxReentrantLock.releaseWrite(lock)
return count
})
await Effect.runPromise(program) // => 1

readLock

Added in v2.0.0 Source

Acquires a read lock for the duration of the scope. The lock is automatically released when the scope closes.

Signature

declare function readLock(self: TxReentrantLock): Effect<number, never, Scope>

Example

(Holding a scoped read lock)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
const held = yield* Effect.scoped(
Effect.gen(function*() {
yield* TxReentrantLock.readLock(lock)
// read lock is held for the duration of the scope
return yield* TxReentrantLock.readLocks(lock)
})
)
// read lock is released
return [held, yield* TxReentrantLock.readLocks(lock)]
})
await Effect.runPromise(program) // => [1, 0]

withLock

Added in v2.0.0 Source

Runs an effect while holding a write lock.

When to use

Use when you need to run an effect with exclusive write access through a TxReentrantLock and prefer the concise lock helper.

Signature

declare const withLock: {
<A, E, R>(effect: Effect<A, E, R>): (self: TxReentrantLock) => Effect<A, E, R>;
<A, E, R>(self: TxReentrantLock, effect: Effect<A, E, R>): Effect<A, E, R>;
}

Example

(Running an effect with exclusive access)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.withLock(
lock,
Effect.succeed("exclusive operation")
)
})
await Effect.runPromise(program) // => "exclusive operation"

withReadLock

Added in v2.0.0 Source

Runs the provided effect while holding a read lock. The lock is automatically released after the effect completes, fails, or is interrupted.

Signature

declare const withReadLock: {
<A, E, R>(effect: Effect<A, E, R>): (self: TxReentrantLock) => Effect<A, E, R>;
<A, E, R>(self: TxReentrantLock, effect: Effect<A, E, R>): Effect<A, E, R>;
}

Example

(Running an effect with a read lock)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.withReadLock(
lock,
Effect.succeed("read data")
)
})
await Effect.runPromise(program) // => "read data"

Runs the provided effect while holding a write lock. The lock is automatically released after the effect completes, fails, or is interrupted.

Signature

declare const withWriteLock: {
<A, E, R>(effect: Effect<A, E, R>): (self: TxReentrantLock) => Effect<A, E, R>;
<A, E, R>(self: TxReentrantLock, effect: Effect<A, E, R>): Effect<A, E, R>;
}

Example

(Running an effect with a write lock)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
return yield* TxReentrantLock.withWriteLock(
lock,
Effect.succeed("wrote data")
)
})
await Effect.runPromise(program) // => "wrote data"

writeLock

Added in v2.0.0 Source

Acquires a write lock for the duration of the scope. The lock is automatically released when the scope closes.

Signature

declare function writeLock(self: TxReentrantLock): Effect<number, never, Scope>

Example

(Holding a scoped write lock)

import { Effect, TxReentrantLock } from "effect"
const program = Effect.gen(function*() {
const lock = yield* TxReentrantLock.make()
const held = yield* Effect.scoped(
Effect.gen(function*() {
yield* TxReentrantLock.writeLock(lock)
// write lock is held for the duration of the scope
return yield* TxReentrantLock.writeLocks(lock)
})
)
// write lock is released
return [held, yield* TxReentrantLock.writeLocks(lock)]
})
await Effect.runPromise(program) // => [1, 0]

Other

Signature

declare function releaseRead(self: TxReentrantLock): Effect<number>

Signature

declare function releaseWrite(self: TxReentrantLock): Effect<number>