# valvekit

> Mutex locks, Read/Write locks, Barriers and Semaphores

Latest version **0.2.0** (published 2019-06-20) · MIT license · 0 weekly downloads

## Install

```sh
npm install valvekit
pnpm add valvekit
yarn add valvekit
bun add valvekit
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.2.0 |
| Published | 2019-06-20 |
| First published | 2018-05-01 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 15.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Devebot |
| Maintainers | devebot |
| Keywords | locks, mutex, semaphore |

## Links

- npm: https://www.npmjs.com/package/valvekit
- Repository: https://github.com/devebot/valvekit
- Homepage: https://github.com/devebot/valvekit#readme
- Issues: https://github.com/devebot/valvekit/issues
- npm.io page: https://npm.io/package/valvekit

## Dependencies (1)

- [bluebird](https://npm.io/package/bluebird.md) ^3.5.5

## Recent versions

- 0.2.0 (latest) — 2019-06-20
- 0.1.3 — 2018-06-13
- 0.1.0 — 2018-05-01

## README

# Valvekit

Valvekit is a locking/synchronization mechanisms library forked from `locks`.
This library implements locking/synchronization mechanisms that have traditionally
been used for protecting shared memory between multiple threads. JavaScript is
inherently single threaded and does not suffer from these security and
stability issues. However, because of its asynchronous eventy nature JavaScript
can still benefit from making particular operations wait for the completion of
others.

## Installation

Node.js users:
```bash
npm install --save valvekit
```

Accessing the `valvekit` module:
```javascript
var valvekit = require('valvekit');
```

### Barrier locks

Barriers allow synchronization between processes based on tickets.

Creating a Barrier:
```javascript
var defaultTicket = 'foo-bar';
var barrier = valvekit.createBarrier(defaultTicket);
```

Waiting for a provided ticket that matching a value of accepted array:

```javascript
barrier.wait(['th3-s3cr3t-k3y', 'invalid'], function matched() {
		console.log('Provided ticket value is matched!');
	}
);
```

or a condition test function to be met:
```javascript
barrier.wait(
	function conditionTest(value) {
		return value.indexOf('s3cr3t') !== -1;
	},
	function whenConditionMet() {
		console.log('Provided ticket value is matched!');
	}
);
```

Setting the ticket on a Barrier:
```javascript
barrier.set('th3-s3cr3t-k3y');
```

### Mutex locks

Mutex locks are the most basic locks which aim to prevent the simultaneous
access to a resource by more than one actor at a time.
[more info](http://en.wikipedia.org/wiki/Mutual_exclusion)

Creating a Mutex Lock:
```javascript
var mutex = valvekit.createMutex();
```

Waiting to lock:
```javascript
mutex.lock(function () {
	console.log('We got the lock!');
	// do stuff
	mutex.unlock();
});
```

Waiting to lock, with timeout:
```javascript
mutex.lock(function (error) {
	if (error) {
		console.log('Could not get the lock within 5 seconds, so gave up');
	} else {
		console.log('We got the lock!');
		// do stuff
		mutex.unlock();
	}
}, 5000);
```

Checking if a lock is held:
```javascript
if (mutex.isLocked) {
	console.log('Something has the lock.');
}
```

Optimistic attempt to lock:
```javascript
if (mutex.tryLock()) {
	console.log('We got the lock!');
	// do stuff
	mutex.unlock();
} else {
	console.log('Could not get the lock at this time');
}
```

### Read/Write locks

Read/Write Locks are used to allow many actors to read from a resource, as
long as nothing is writing to it. That also means that only one actor may be
writing at any given time.
[more info](http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock)

Creating a Read/Write Lock:
```javascript
var rwlock = valvekit.createLock();
```

Waiting to read lock:
```javascript
rwlock.readLock(function () {
	console.log('We may now read from a resource!');
	// do stuff
	rwlock.unlock();
});
```

Waiting to read lock, with timeout:
```javascript
rwlock.readLock(function (error) {
	if (error) {
		console.log('Could not get the lock within 5 seconds, so gave up');
	} else {
		console.log('We may now read from a resource!');
		// do stuff
		rwlock.unlock();
	}
}, 1000);
```

Waiting to write lock:
```javascript
rwlock.writeLock(function () {
	console.log('We may now write to a resource!');
	// do stuff
	rwlock.unlock();
});
```

Waiting to write lock, with timeout:
```javascript
rwlock.writeLock(function (error) {
	if (error) {
		console.log('Could not get the lock within 5 seconds, so gave up');
	} else {
		console.log('We may now write to a resource!');
		// do stuff
		rwlock.unlock();
	}
}, 5000);
```

Checking if a lock is held:
```javascript
if (rwlock.isWriteLocked) {
	console.log('Something has the write lock.');
}
else if (rwlock.isReadLocked) {
	console.log('The read lock is held one or more times.');
}
```

Optimistic attempt to read lock:
```javascript
if (rwlock.tryReadLock()) {
	console.log('We may now read from a resource!');
	// do stuff
	rwlock.unlock();
} else {
	console.log('Could not get the lock at this time');
}
```

Optimistic attempt to write lock:
```javascript
if (rwlock.tryWriteLock()) {
	console.log('We may now write to a resource!');
	// do stuff
	rwlock.unlock();
} else {
	console.log('Could not get the lock at this time');
}
```

### Semaphores

Semaphores solve the problem of sharing a limited set of resources.
[more info](http://en.wikipedia.org/wiki/Semaphore_%28programming%29)

Creating a Semaphore:
```javascript
var resourceLimit = 3;  // amount of resources available
var sem = valvekit.createSemaphore(resourceLimit);
```

Claiming and releasing a resource:
```javascript
sem.take(function () {
	// a resource is available, do something
	// ...
	// done, release the resource
	sem.release();
});
```

Or using an all-in-one function:

```javascript
sem.sandbox(function () {
	// a resource is available, do something
	// ...
	// automatic release the resource
});
```

Example:

```javascript
var sem = require('valvekit').createSemaphore(5);

function demo(i) {
  return sem.sandbox(function() {
    if (Math.random() > 0.7) {
      throw new Error("Item[" + i + "] - accident");
    }
    return new Promise(function(resolved, rejected) {
      setTimeout(function() {
        if (Math.random() > 0.5) 
					rejected("Item[" + i + "] - rejected");
				else
					resolved("Item[" + i + "]");
      }, 100)
    })
  })
}

function show(msg) {
	console.log(typeof msg === 'string' ? msg : msg.message);
}

var count = 0;
for(var i=0; i<100; i++) {
  demo(i).then(show, show).finally(function() {
    count++;
    console.log("current: %d", count);
  });
}
```

## License

MIT

---
_Source: https://npm.io/package/valvekit · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
