Skip to content

Commit

Permalink
docs: Readme update
Browse files Browse the repository at this point in the history
  • Loading branch information
orimay committed Feb 13, 2025
1 parent 8c2f5d9 commit 8174703
Showing 1 changed file with 78 additions and 9 deletions.
87 changes: 78 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
### mutex-ts

This package provides two classes for managing locks: `Mutex` and `MutexRW`.
These locks can be used to control access to critical sections in a
multi-threaded or asynchronous environment.
This package provides two classes for managing locks in asynchronous (and
multi-threaded-like) environments: `Mutex` and `MutexRW`. Use these locks to
protect critical sections in your code, ensuring that only one task (or a
controlled number of tasks) can access a shared resource at a time.

> **Note:** The `lock()`, `lockRO()`, and `lockRW()` methods return objects that
> implement a disposable interface via the `[Symbol.dispose]` property. This
> allows you to use the upcoming `using` statement to automatically release
> locks at the end of a scope.
#### Installation

To install the package, you can use npm or yarn:
To install the package, you can use npm, yarn or pnpm:

```bash
npm install mutex-ts
# or
yarn add mutex-ts
# or
pnpm add mutex-ts
```

#### Usage
Expand All @@ -20,6 +28,10 @@ yarn add mutex-ts

The `Mutex` class provides a simple mutual exclusion lock.

##### Manual Lock Management

You can manually acquire and release the lock with obtain():

```typescript
import { Mutex } from 'mutex-ts';

Expand Down Expand Up @@ -59,11 +71,33 @@ yarn add mutex-ts
This allows you to make the decision to bypass the lock based on a runtime
condition, ensuring flexibility in your locking strategy.

##### Using Disposable Locks with `using`

Alternatively, use the new `lock()` method to obtain a disposable lock object
that automatically releases the lock when the scope ends. (This works in
TypeScript with the upcoming `using` syntax.)

```typescript
import { Mutex } from 'mutex-ts';

async function criticalSectionUsing() {
const mutex = new Mutex();
// Using the "using" pattern (requires proper TS configuration/polyfill)
{
using _ = await mutex.lock();
// Critical section code goes here.
// When the block exits, _[Symbol.dispose]() is called, releasing the lock.
}
}
```

2. **MutexRW:**

The `MutexRW` class provides a more complex lock supporting multiple readers
and a single writer.

##### Manual Lock Management

```typescript
import { MutexRW } from 'mutex-ts';

Expand Down Expand Up @@ -94,12 +128,47 @@ yarn add mutex-ts
readers release their locks. Using `try...finally` blocks ensures that locks
are correctly released, preventing deadlocks or other synchronization issues.

#### Important Note
##### Using Disposable Locks with `using`

Alternatively, use the new `lockRO()` and `lockRW()` methods to obtain a
disposable lock object that automatically releases the lock when the scope
ends. (This works in TypeScript with the upcoming `using` syntax.)

```typescript
import { MutexRW } from 'mutex-ts';

const mutexRW = new MutexRW();

{
// Obtain a read lock
using _ = await mutexRW.obtainRO();

// Automatic release of the read lock in the end of the block
}

{
// Obtain a write lock
using _ = await mutexRW.obtainRW();

// Automatic release of the write lock in the end of the block
}
```

Please make sure to handle lock release in a `finally` block as shown in the
examples to ensure proper synchronization and resource cleanup. When using the
`bypass` parameter, the decision to bypass the lock should be determined at
runtime based on your application's logic.
#### Important Notes

- **Automatic Disposal**: The objects returned by `lock()`, `lockRO()`, and
`lockRW()` have a `[Symbol.dispose]` property. When used with the upcoming
using syntax, the corresponding lock is automatically released when the
variable goes out of scope.
- **Bypass Option**: Passing true to `obtain()` skips waiting for the lock,
returning a release function (or no-op, if lock is not acquired). This can be
useful when you want to conditionally enter a critical section.
- **Integration**: Ensure your TypeScript configuration (or polyfill) supports
the `using` syntax and the disposable feature (i.e. having the correct `"lib"`
settings such as including `"esnext"` or `"esnext.disposable"`).
- If you are using manual lock management, please make sure to handle lock
release in a `finally` block as shown in the examples to ensure proper
synchronization and resource cleanup.

For further details, you can refer to the source code and comments within the
package.
Expand Down

0 comments on commit 8174703

Please sign in to comment.