UNPKG

dahlia-concurrency

Version:

High-level concurrency primitives and patterns for Node.js using worker_threads (queues, semaphore, mutex, worker pool, scheduler, and more)

100 lines (83 loc) 2.16 kB
const { Mutex } = require("./mutex.js"); class RwLock { constructor(readMutexBuffer, writeMutexBuffer, politics = true) { this.politics = politics; // true is fair // false is greedy this.reader = 0; this.writer = false; this.readMutex = new Mutex(readMutexBuffer); this.writeMutex = new Mutex(writeMutexBuffer); if (politics) { this.waitingWriters = 0; const readerGateBuffer = new SharedArrayBuffer(4); this.readerGate = new Mutex(readerGateBuffer); } } readLockGreedy() { this.readMutex.lock(); this.reader++; if (this.reader === 1) { this.writeMutex.lock(); } this.readMutex.unlock(); } readLockFair() { this.readerGate.lock(); this.readMutex.lock(); this.reader++; if (this.reader === 1) { this.writeMutex.lock(); } this.readMutex.unlock(); this.readerGate.unlock(); } writeLockGreedy() { this.readMutex.lock(); if (this.reader > 0) { this.readMutex.unlock(); throw new Error("Cannot acquire write lock while read lock is active"); } this.readMutex.unlock(); this.writeMutex.lock(); this.writer = true; } writeLockFair() { this.readMutex.lock(); if (this.reader > 0) { this.readMutex.unlock(); throw new Error("Cannot acquire write lock while read lock is active"); } this.readMutex.unlock(); this.waitingWriters++; this.readerGate.lock(); this.writeMutex.lock(); this.writer = true; this.waitingWriters--; } readLock() { return this.politics ? this.readLockFair() : this.readLockGreedy(); } writeLock() { return this.politics ? this.writeLockFair() : this.writeLockGreedy(); } readUnlock() { this.readMutex.lock(); this.reader--; if (this.reader === 0) { this.writeMutex.unlock(); if (this.politics && this.waitingWriters > 0) { this.readerGate.unlock(); } } this.readMutex.unlock(); } writeUnlock() { this.writer = false; this.writeMutex.unlock(); if (this.politics) { this.readerGate.unlock(); } } } module.exports = { RwLock };