Skip to content

Instantly share code, notes, and snippets.

@shovon
Last active February 27, 2019 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shovon/8059699e31fc449a8479a6f177218ff2 to your computer and use it in GitHub Desktop.
Save shovon/8059699e31fc449a8479a6f177218ff2 to your computer and use it in GitHub Desktop.

JavaScript is in no way immune from race conditions.

With JavaScript's most common use case being web application (both front-end and back-end), input and output are therefore not synchronous. Hence the need devise synchronization paradigmes. Transactional integrity, for example, will greatly benefit from any such exercise.

Below is an example usage of a createMutex function that was written in the aim of introducing a primitive similar to mutex locks to JavaScript.

Usage

const { createMutexLock } = require('./mutex');

const acquireLock = createMutexLock();

const someFunctionWithCriticalSection = async () => {
  
  await acquireLock(async () => {
    await foo();
    await bar();
    await baz();
  });
  
};

Promise.all([
  someFunctionWithCriticalSection(),
  someFunctionWithCriticalSection()
])
  .catch(error => { console.error(error); })

Without mutex

const someFunctionWithCriticalSection = async () => {
  
  // These, collectively, represent critical sections
  await foo();
  await bar();
  await baz();
  
};

Promise.all([
  someFunctionWithCriticalSection(),
  someFunctionWithCriticalSection()
])
  .catch(error => { console.error(error); })
/**
* Create a promise-returning function that accepts another promise-returning
* function as its parameter. Call it for some transactional integrity,
* at least at the process level
*
* @returns {(param: () => Promise) => Promise}
*/
const createMutexLock = () => {
let locked = false;
let listeners = [];
const runNextListener = () => {
const listener = listeners.pop();
if (!listener) {
locked = false;
return;
}
listener()
.then(
() => { runNextListener(); },
() => { runNextListener(); }
);
};
const run = listener => new Promise((resolve, reject) => {
listeners.unshift(() => {
return listener().then(
() => { resolve(); },
error => { reject(error); }
);
});
if (!locked) {
locked = true;
runNextListener();
}
});
return run;
};
module.exports.createMutexLock;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment