{"id":23911941,"url":"https://github.com/robtimus/concurrent-ts","last_synced_at":"2025-02-23T17:44:46.409Z","repository":{"id":270979564,"uuid":"745891926","full_name":"robtimus/concurrent-ts","owner":"robtimus","description":"Utility classes commonly useful in concurrent programming","archived":false,"fork":false,"pushed_at":"2025-02-18T19:07:02.000Z","size":324,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-18T20:24:24.498Z","etag":null,"topics":["concurrent","javascript","nodejs","typescript"],"latest_commit_sha":null,"homepage":"https://robtimus.github.io/concurrent-ts","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robtimus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-20T13:16:31.000Z","updated_at":"2025-02-18T19:07:06.000Z","dependencies_parsed_at":"2025-01-04T15:17:18.814Z","dependency_job_id":"c368fbc1-6428-4106-b769-e677c2a92d70","html_url":"https://github.com/robtimus/concurrent-ts","commit_stats":null,"previous_names":["robtimus/concurrent-ts"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fconcurrent-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fconcurrent-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fconcurrent-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fconcurrent-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robtimus","download_url":"https://codeload.github.com/robtimus/concurrent-ts/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240356098,"owners_count":19788512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrent","javascript","nodejs","typescript"],"created_at":"2025-01-05T08:57:27.587Z","updated_at":"2025-02-23T17:44:46.376Z","avatar_url":"https://github.com/robtimus.png","language":"TypeScript","readme":"# @robtimus/concurrent\n[![npm](https://img.shields.io/npm/v/@robtimus/concurrent)](https://www.npmjs.com/package/@robtimus/concurrent)\n[![Build Status](https://github.com/robtimus/concurrent-ts/actions/workflows/build.yml/badge.svg)](https://github.com/robtimus/concurrent-ts/actions/workflows/build.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=robtimus%3Aconcurrent\u0026metric=alert_status)](https://sonarcloud.io/summary/overall?id=robtimus%3Aconcurrent)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=robtimus%3Aconcurrent\u0026metric=coverage)](https://sonarcloud.io/summary/overall?id=robtimus%3Aconcurrent)\n[![Known Vulnerabilities](https://snyk.io/test/github/robtimus/concurrent-ts/badge.svg)](https://snyk.io/test/github/robtimus/concurrent-ts)\n\n## [CountDownLatch](https://robtimus.github.io/concurrent-ts/classes/CountDownLatch.CountDownLatch.html)\n\nA locking mechanism that allows one or more tasks to wait until a set of operations being performed in other tasks completes.\nIt's inspired by Java's [CountDownLatch](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CountDownLatch.html).\n\nA `CountDownLatch` is initialized with a non-negative count. The promises returned by the `await()` method do not resolve until the current count reaches 0 due to calls to the `countDown()` method. This can occur only once, the count cannot be reset.\n\nThe promises returned by the `await(timeout)` are rejected if the timeout expires before the current count reaches 0. To get a `false` like Java's `CountDownLatch`, simply use `catch`:\n\n```typescript\nif (await latch.await(timeout).catch(() =\u003e false) !== false) {\n  // count reached 0\n} else {\n  // timeout expired\n}\n```\n\n### Sample usage\n\n```typescript\nconst startLatch = new CountDownLatch(1);\nconst readyLatch = new CountDownLatch(10);\nconst finishLatch = new CountDownLatch(10);\n\nfor (let i = 0; i \u003c 10; i++) {\n  new Promise((resolve, reject) =\u003e {\n    // tell the calling code this promise is ready to start\n    readyLatch.countDown();\n    // wait for the calling code to let all promises start\n    startLatch.await()\n      .then(() =\u003e {\n        /* do work and call resolve / reject as needed */\n      })\n      .finally(() =\u003e {\n        // tell the calling code this promise is done\n        finishLatch.countDown();\n      });\n  });\n}\n\n// wait for all promises to be ready to start\nawait readyLatch.await();\n// let all promises start\nstartLatch.countDown();\n// wait for all promises to be done\nawait finishLatch.await();\n```\n\n## [Semaphore](https://robtimus.github.io/concurrent-ts/classes/Semaphore.Semaphore.html)\n\nA port of Java's [Semaphore](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/Semaphore.html).\n\nA `Semaphore` is initialized with a non-negative number of permits. The promises returned by the `acquire()` and `acquire(permits)` methods do not resolve until enough permits are available, either because the current number is sufficient or because `release()` or `release(permits)` is called.\n\nThe promises returned by the `tryAcquire()` and `tryAcquire(permits)` methods resolve with `true` if enough permits are available, or `false` otherwise.\n\nThe promises returned by the `tryAcquire(options)` method resolve with `true` if enough permits become available before the timeout expires, or `false` otherwise.\n\n### Sample usage\n\n```typescript\nconst semaphore = new Semaphore(0);\n// set if semaphore.availablePermits() \u003e 0\nlet value: string;\n\nfunction getValue(): Promise\u003cstring\u003e {\n  return semaphore.acquire().then(() =\u003e value);\n}\n\nfunction setValue(v: string): void {\n  value = v;\n  semaphore.release();\n}\n```\n\n## [ReadWriteLock](https://robtimus.github.io/concurrent-ts/classes/ReadWriteLock.ReadWriteLock.html)\n\nA locking mechanism that allows multiple concurrent readers, but only one writer at a time.\nIt's inspired by both Java's [ReadWriteLock](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/locks/ReadWriteLock.html) and .NET's [ReaderWriterLockSlim](https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim).\nUnlike both of these, acquiring a lock returns an object that implements [ReadLock](https://robtimus.github.io/concurrent-ts/interfaces/ReadWriteLock.ReadLock.html) or [WriteLock](https://robtimus.github.io/concurrent-ts/interfaces/ReadWriteLock.WriteLock.html). This allows a specific lock to be released, something that's enforced in Java and .NET by releasing locks on the same thread on which they were acquired.\n\n### Fairness\n\nBy default a `ReadWriteLock` is fair. That means that if there are active read locks and pending write locks, new read locks will not be acquired immediately. This prevents readers from blocking writers indefinitely.\n\nTo let new read locks be acquired immediately if at least one read lock is active, set the fairness to `false`:\n\n```typescript\nconst lock = new ReadWriteLock({\n  fair: false,\n});\n```\n\n### Sample usage\n\n```typescript\nclass CachedData\u003cT\u003e {\n  private data?: T;\n  private cacheValid = false;\n  private lock = new ReadWriteLock();\n\n  async processCachedData() {\n    let readLock = await this.lock.acquireReadLock();\n    if (!this.cacheValid) {\n      // Unlike in Java, locks can be upgraded directly\n      // Unlike in .NET, any read lock can be upgraded\n      const writeLock = await readLock.upgradeToWriteLock();\n      try {\n        // Recheck state because another invocation might have acquired the write lock\n        // and changed data before the upgrade has completed.\n        if (!this.cacheValid) {\n          this.data = ...;\n          this.cacheValid = true;\n        }\n      } finally {\n        readLock = writeLock.downgradeToReadLock();\n      }\n    }\n    try {\n      use(this.data);\n    } finally {\n      readLock.release();\n    }\n  }\n}\n```\n\n## [ConcurrentMap](https://robtimus.github.io/concurrent-ts/classes/ConcurrentMap.ConcurrentMap.html)\n\nAn object similar to [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) that allows concurrent modification.\nIt's inspired by Java's [ConcurrentHashMap](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html).\n\n### Sample usage\n\n```typescript\nclass CachedData\u003cK, V\u003e {\n  private map = new ConcurrentMap\u003cK, V\u003e();\n\n  async processCachedData(key: K) {\n    return this.map.compute(key, (k, v) =\u003e {\n      if (this.isValid(v)) {\n        return v;\n      }\n      return this.calculate(k);\n    });\n  }\n\n  private isValid(value?: V) {\n    return value !== undefined \u0026\u0026 ...;\n  }\n\n  private async calculate(key: K) {\n    return ...\n  }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtimus%2Fconcurrent-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobtimus%2Fconcurrent-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtimus%2Fconcurrent-ts/lists"}