# `Reactor.Executor.ConcurrencyTracker`
[🔗](https://github.com/ash-project/reactor/blob/main/lib/reactor/executor/concurrency_tracker.ex/#L6)

Manage shared concurrency pools for multiple Reactors.

When running a Reactor you can pass the `concurrency_key` option, which will
cause the Reactor to use the specified pool to ensure that the combined
Reactors never exceed the pool's available concurrency limit.

This avoids nested Reactors spawning too many workers and thrashing the
system.

The process calling `allocate_pool/1` is monitored, and when it terminates
it's allocation is removed.  Any processes which are using that pool will
not be able to allocate any new resources.

# `pool_key`

```elixir
@type pool_key() :: reference()
```

# `pool_record`

```elixir
@type pool_record() ::
  {pool_key(), concurrency_limit :: pos_integer(),
   available_slots :: non_neg_integer(), allocator :: pid()}
```

# `acquire`

```elixir
@spec acquire(pool_key(), how_many :: non_neg_integer()) :: {:ok, non_neg_integer()}
```

Attempt to acquire a number of concurrency allocations from the pool.

Returns `{:ok, n}` where `n` was the number of slots that were actually
allocated.  It's important to note that whilst you may request `16` slots, if
there is only `3` available, then this function will return `{:ok, 3}` and you
must abide by it.

It is possible for this function to return `{:ok, 0}` if there is no slots
available.

# `allocate_pool`

```elixir
@spec allocate_pool(non_neg_integer()) :: pool_key()
```

Allocate a new concurrency pool and set the maximum limit.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `release`

```elixir
@spec release(pool_key(), how_many :: non_neg_integer()) :: :ok | :error
```

Release concurrency allocation back to the pool.

# `release_on_exit`

```elixir
@spec release_on_exit(pool_key(), pid()) :: :ok
```

Release a concurrency allocation back to the pool when the given process exits.

# `release_pool`

```elixir
@spec release_pool(pool_key()) :: :ok
```

Release the concurrency pool.

This deletes the pool, however doesn't affect any processes currently using
it.  No more resources can be acquired by users of the pool key.

# `status`

```elixir
@spec status(pool_key()) :: {:ok, available, limit} | {:error, any()}
when available: non_neg_integer(), limit: pos_integer()
```

Report the available and maximum concurrency for a pool.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
