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 🙏

© 2024 – Pkg Stats / Ryan Hefner

sem-lib

v2.6.4

Published

A semaphore library for nodejs

Downloads

21

Readme

sem-lib

A semaphore library for nodejs

  • Limit simultaneous access to resources
  • Synchronize multiple tasks
// Create
const SemLib = require("sem-lib");
const semID = SemLib.semCreate();

// wait for a token
semID.semTake(callback);

// Add a token to the semaphore
SemLib.semGive();
// Exclusive access
const SemLib = require("sem-lib");
const semID = SemLib.semCreate(1, true);

semID.semTake(function() {
  // first exclusive access
  ...
  semID.semGive();
});

semID.semTake(function() {
  // second exclusive access
  ...
  semID.semGive();
});
// Synchronization
const SemLib = require("sem-lib");
const semID = SemLib.semCreate(3, true);

function AsyncTask1(semID) {
  console.log("AsyncTask1");
  semID.semGive();
}

function AsyncTask2(semID) {
  console.log("AsyncTask2");
  semID.semGive();
}

function AsyncTask3(semID) {
  console.log("AsyncTask3");
  semID.semGive();
}

setTimeout(function() {
  AsyncTask1(semID);
}, 200);

setTimeout(function() {
  AsyncTask2(semID);
}, 100);

setTimeout(function() {
  AsyncTask3(semID);
}, 300);

semID.semTake(3, function(){
  //Executed after AsyncTask1, AsyncTask2 and AsyncTask3
  console.log("After all tasks");
});
// Limit simultaneous access
// You have multiple downloads to do and you don't want to blow up your memory nor your cpu

const SemLib = require("sem-lib");

// At most 8 simultanenous downloads
const semID = SemLib.semCreate(8, true);

require('fs').readFile('links', function(err, data) {
    if (err) {
        throw err;
    }
    const links = data.toString().trim().split(/\r?\n/);
    semID.schedule(links, (link, i, next) => {
        console.log(`downloading ${ link }`);
        download(link, next);
    }, () => {
        console.log(`downloaded ${ links.length } links`);
    });
});

SemLib

SemLib.semCreate(capacity, isFull, priority, sync = false)

Create a semaphore. See Semaphore#constructor() for more detauls

SemLib.Semaphore

See the Semaphore Class

Semaphore : Class

constructor(capacity, isFull, priority, sync = false)

| Option | Type | Optional | Default | Description | |-------------|-----------|:---------:|---------|-----------------------------------------------------------------| | capacity | Integer | Yes | 1 | Number of available tokens. i.e. how much concurrency | | isFull | Boolean | Yes | false | Create semaphore with all tokens available | | priority | Integer | Yes | 15 | Default take priority. Lower values means higher priority | | sync | Boolean | Yes | false | Run tasks synchronously instead of waiting for the next tick |

semTake(task : Function) : Inwaiting

Shortcut to semTake({onTake: task})

semTake(settings : Object) : Inwaiting | false

Wait for the Semaphore availability before calling onTake callback.

Returns false if the semaphore has been destroyed.

task()

Function to call when all the tokens have been taken.

shouldTakeToken(availableTokens : Integer, missingTokens : Integer, alreadyTakenTokens : Integer, semID : Semaphore) : Boolean

In case you want to allow the waiting task to take tokens only if certains conditions are met.

hasMissingToken(semID : Semaphore)

Called when there are not enough token for the task.

Other options

| Option | Type | Optional | Default | Description | |-------------------|-------------|:---------:|---------------------|---------------------------------------------------------------------------------| | priority | Integer | Yes | Semaphore priority | Task priority. Lower values means higher priority | | num | Integer | Yes | 1 | Number of tokens to take | | timeOut | Integer | Yes | undefined | Time to wait until the task is abandoned | | onTimeOut | Function | Yes | undefined | Function to call when waiting has reached timeout | | onCancel | Function | Yes | undefined | Function to call when waiting has been canceled | | unfair | Boolean | Yes | false | Allows to take tokens from waiting tasks with lower priorities | | sync | Boolean | Yes | undefined | Run this task synchronously. If not defined, honor the semaphore sync option |

semGive(num : Integer, overflow: Boolean)

Give the number of tokens to the semaphore.

By default, a semaphore cannot receive more tokens than its capacity.
overflow allows temporary capacity overflow.
During the semGive process, getNumTokens() + num will the number of available tokens.
At the end of the semGive process, then number of available tokens will not exceed the semaphore capacity.

semFlush()

Run all waiting tasks

getNumTokens() : Integer

Return the number of available tokens

getCapacity() : Integer

Return the maximum of available tokens

setCapacity(capacity: Integer)

Set the maximum of available tokens

schedule : Inwaiting

Run a collection of tasks, take one token for each task.

Queuing millions of tasks in the semaphore will use a lot of memory.
For that reason, when you have a collection of tasks, prefer using schedule.
It is faster and uses less memory. See benchmark/memory-profile.js for an example.

Usage

schedule(collection : Array | Iterable | Object, priority : Integer)
schedule(collection : Array | Iterable | Object, callback : Function)
schedule(collection : Array | Iterable | Object, priority : Integer, callback : Function)
schedule(collection : Array | Iterable | Object, iteratee : Function, callback : Function)
schedule(collection : Array | Iterable | Object, priority : Integer, iteratee : Function, callback : Function)

Examples

const semID = semLib.semCreate(3, true); // 3 tokens full
semID.schedule([
    next => {
      // task 1
      next()
    },
    next => {
      // task 2
      next()
    }
], () => {
    // All tasks were run;
});
const semID = semLib.semCreate(3, true); // 3 tokens ful

semID.schedule([
    [/* args 1 */],
    [/* args 2 */],
], (args, i, next) => {
    // process args
    next();
}, () => {
    // All args were processed;
});
const semID = semLib.semCreate(3, true); // 3 tokens full
semID.schedule({
    s1: next => { /* task 1 */; next() },
    s2: next => { /* task 2 */; next() },
}, () => {
    // All tasks were run;
});
const semID = semLib.semCreate(3, true); // 3 tokens full

semID.schedule({
    s1: [ /* args 1 */ ],
    s2: [ /* args 2 */ ],
}, (args, key, next) => {
    // process args
    next();
}, () => {
    // All args were processed;
});

destroy(safe, onDestroy)

Destroy all inwaiting tasks

Parameters

safe: Boolean, optional, default: undefined, if not false, wait for all inwaiting tasks to be performed, else, cancel inwaiting tasks and destroy onDestroy: Function optional, Called after semaphore destruction

Inwaiting : Class

addCounter(num : Integer)

The task should take more tokens before running

setPriority(priority : Integer)

Change the task priority

cancel()

Cancel the task

License

The MIT License (MIT)

Copyright (c) 2014-2019 Stéphane MBAPE (https://smbape.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.