Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jcoglan
Last active May 26, 2016 18:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcoglan/73e8eebc81897ee08fe1cb384a220357 to your computer and use it in GitHub Desktop.
Save jcoglan/73e8eebc81897ee08fe1cb384a220357 to your computer and use it in GitHub Desktop.
const getAllPropertyNames = require('./get_all_property_names'),
Mutex = require('./mutex')
function actor(object) {
let methods = getAllPropertyNames(object),
mutex = new Mutex(),
wrapper = {}
for (let method of methods) {
if (typeof object[method] !== 'function') continue
wrapper[method] = actorMethodDescriptor(mutex, object, method)
}
return Object.create(object, wrapper)
}
function actorMethodDescriptor(mutex, object, method) {
return {
value: (...args) => {
return mutex.synchronize(() => object[method](...args))
}
}
}
module.exports = actor
const IGNORE_NAMES = Object.getOwnPropertyNames(Object.prototype)
function getAllPropertyNames(object) {
let set = new Set()
while (object !== Object.prototype) {
for (let name of Object.getOwnPropertyNames(object)) {
if (IGNORE_NAMES.indexOf(name) < 0) set.add(name)
}
object = Object.getPrototypeOf(object)
}
return set
}
module.exports = getAllPropertyNames
class Mutex {
constructor() {
this._busy = false
this._queue = []
}
synchronize(task) {
return new Promise((resolve, reject) => {
this._queue.push([task, resolve, reject])
if (!this._busy) this._execute()
})
}
_execute() {
this._busy = true
let next = this._queue.shift()
if (!next) return this._busy = false
let [task, resolve, reject] = next,
execute = () => this._execute(),
promise = Promise.resolve(task())
promise.then(resolve, reject)
.then(execute, execute)
}
}
module.exports = Mutex
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment