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

spsc

v0.0.7

Published

Single-producer-single-consumer queue that adheres to POSIX's pipe semantics.

Readme

spsc

Single-producer-single-consumer queue that adheres to POSIX's pipe semantics.

Note that this package requires a cross-origin-isolated (COI) context if run in a browser.

The package is developed as a minimal solution to implement efficient-enough, synchronous, blocking I/O between WASM/WASI with browser's JS host.

Usage

Make a SharedArrayBuffer and share it between two execution contexts ( preferably workers). At either end, initialize SPSCReader and SPSCWriter accordingly. Send message to the writer side, and receive it from the reader side. A PoC writer should look like:

import { SPSC } from 'spsc'
import { SPSCWriter } from 'spsc/writer'

const sab = SPSC.allocateArrayBuffer(256)
const writer = new SPSCWriter(sab)
writer.write(new Uint8Array([1, 2, 3]))  // -> { ok: true, bytesWritten: 3 }

Here is the reader part:

import { SPSCReader } from 'spsc/reader'
var sab  // suppose the sab is cloned
const reader = new SPSCReader(sab)
reader.read(3)  // -> { ok: true, bytesRead: 3, data: Uint8Array [1, 2, 3] }
const ready = reader.pollRead(1000)  // -> false
reader.close()

Note that readers and writers do not throw on I/O errors. It is your own responsibility (i.e. freedom) to check the result.

Using in browser main thread

Note that blocking I/O behavior is done with Atomics.{wait,notify} by default. If your thread does not allow pausing (e.g., browser main thread), this library provides an alternative (but not air-tight) way:

Let's suppose that your reader lives in the main thread. To adopt this pattern, create a MessageChannel and transfer one of either port into the other end (in this example, the writer):

const msgchan = new MessageChannel()

const writer = new SPSCWriter(
  sab,
  msgchan.port1,  // the one end
  true  // (optional) token, default to true
)

The reader should listen to the other end to retry a nonblocking read. This technique effectively turns the blocking I/O pattern into a cooperative scheduling one.

let pendingRead

// suppose `port` is the transferred `msgchan.port2`
port.onmessage = event => {
  // do nothing if we are not waiting
  if (pendingRead == null) return
  // regaining the control
  pendingRead()
  pendingRead = undefined
}

while (true) {
  const result = reader.read(1, { nonblock: true })  // MUST always be nonblocking
  if (!result.ok) {
    if (result.error === SPSCError.Again) {
      // yielding the control
      await new Promise(resolve => pendingRead = resolve)
      // retry
      continue
    } else {
      throw new Error('read failed')
    }
  }
  // do something with the result
}