Skip to content

Instantly share code, notes, and snippets.

@mbuczko
Created December 1, 2020 16:04
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 mbuczko/6a09d76e325229e3376f59e022eb1d88 to your computer and use it in GitHub Desktop.
Save mbuczko/6a09d76e325229e3376f59e022eb1d88 to your computer and use it in GitHub Desktop.
js / lamport lock with promises
function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
function lamportMutex(id) {
const X = '_lock-X',
Y = '_lock-Y';
const set = (k, v) => localStorage.setItem(k, v),
get = (k) => localStorage.getItem(k),
isFree = (k) => {
let v = get(k);
return v === undefined || v === null;
};
return {
acquire: function() {
return this.lock(0);
},
release: function() {
set(Y, null);
},
lock: function(retries) {
const retry = (resolve, reject) => {
window.requestAnimationFrame(() => {
this.lock(retries + 1).then(resolve, reject);
});
};
set(X, id);
return new Promise((resolve, reject) => {
if (isFree(Y) || retries > 100) {
set(Y, id);
if (get(X) === id) {
resolve();
} else {
window.requestAnimationFrame(() => {
if (get(Y) === id) {
resolve();
} else {
retry(resolve, reject);
}
});
}
} else retry(resolve, reject);
});
}
};
}
const mtx = lamportMutex(uuidv4());
// start requesting a new token every second
setInterval(() => {mtx.acquire().then(
() => {
console.log('getTokenSilently');
a0.getTokenSilently({timeoutInSeconds: 5}).then((t) => mtx.release());
});
}, 500);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment