npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

valvekit

v0.2.0

Published

Mutex locks, Read/Write locks, Barriers and Semaphores

Downloads

112

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:

npm install --save valvekit

Accessing the valvekit module:

var valvekit = require('valvekit');

Barrier locks

Barriers allow synchronization between processes based on tickets.

Creating a Barrier:

var defaultTicket = 'foo-bar';
var barrier = valvekit.createBarrier(defaultTicket);

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

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

or a condition test function to be met:

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:

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

Creating a Mutex Lock:

var mutex = valvekit.createMutex();

Waiting to lock:

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

Waiting to lock, with timeout:

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:

if (mutex.isLocked) {
	console.log('Something has the lock.');
}

Optimistic attempt to lock:

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

Creating a Read/Write Lock:

var rwlock = valvekit.createLock();

Waiting to read lock:

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

Waiting to read lock, with timeout:

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:

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

Waiting to write lock, with timeout:

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:

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:

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:

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

Creating a Semaphore:

var resourceLimit = 3;  // amount of resources available
var sem = valvekit.createSemaphore(resourceLimit);

Claiming and releasing a resource:

sem.take(function () {
	// a resource is available, do something
	// ...
	// done, release the resource
	sem.release();
});

Or using an all-in-one function:

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

Example:

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