# Locks API for Python

Every public class, function and type of the Locks engine in `tinystore`, generated from its source. The [Locks guide](https://tinyshed.org/tinystore/docs/guides/locks) explains how to use them, and the [Bun and Node](https://tinyshed.org/tinystore/docs/reference/bun/locks), [Go](https://tinyshed.org/tinystore/docs/reference/go/locks) and [Rust](https://tinyshed.org/tinystore/docs/reference/rust/locks) pages list the same API.

## Lease

```python
@dataclass(frozen=True, slots=True)
class Lease:
    fence: int  # grows with every lease the store gives, 128 bits: hand it to whatever must refuse a late holder
```

A holding of a lock's key.

## Permit

```python
@dataclass(frozen=True, slots=True)
class Permit:
    ...
```

A holding of a semaphore's key: one of its limit.

## Holding

```python
class Holding[V]:
    ...
```

A hold of a key for the block of an `async with`, which gives what the block holds it by.

A lease lost while the block runs cancels it at its next await, as
`asyncio.timeout` does, and the block ends LostError; one lost after its
last await ends it LostError too, since another holder may have run beside it.

## Lock

```python
class Lock:
    name: str
```

Keys held one holder at a time: `store.lock(name)`.

### Lock.hold

```python
def hold(key: Key, *, wait: Duration = _WAIT) -> Holding[Lease]: ...
```

Waits for key in line and holds it through the block: `async with invoices.hold(id) as lease:`.

A key still held after wait is InUseError; a lease lost while the
block ran is LostError, though the block succeeded.

### Lock.try_hold

```python
def try_hold(key: Key) -> Holding[Lease | None]: ...
```

Holds key through the block if nobody holds it; the lease is None when somebody does.

## Semaphore

```python
class Semaphore:
    name: str
    limit: int
```

Keys held by up to their limit at a time: `store.semaphore(name, limit=3)`.

### Semaphore.hold

```python
def hold(key: Key, *, wait: Duration = _WAIT) -> Holding[Permit]: ...
```

Waits for one of key's permits in line and holds it through the block.

### Semaphore.try_hold

```python
def try_hold(key: Key) -> Holding[Permit | None]: ...
```

Holds one of key's permits through the block if one is free; None when none is.
