Skip to content

Instantly share code, notes, and snippets.

@shotamatsuda
Last active November 19, 2016 05:51
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 shotamatsuda/c31ea61e9100738b9d23763a13d2b5d9 to your computer and use it in GitHub Desktop.
Save shotamatsuda/c31ea61e9100738b9d23763a13d2b5d9 to your computer and use it in GitHub Desktop.
import Namespace from '../core/Namespace'
const self = undefined
const internal = Namespace()
class Task {
constructor(semaphore, callback) {
const promises = [
new Promise((resolve, reject) => {
this.resolve = resolve
this.reject = reject
}),
new Promise(resolve => {
this.let = resolve
}).then(() => {
callback(this.resolve, this.reject)
}),
]
this.promise = Promise.all(promises)
.then(values => {
semaphore.signal()
return values[0]
}, reason => {
semaphore.signal()
return Promise.reject(reason)
})
}
}
export default class Semaphore {
constructor(capacity) {
const self = internal(this)
self.capacity = capacity
self.available = capacity
self.queue = []
}
wait(callback) {
const self = internal(this)
const task = new Task(this, callback)
if (self.available === 0) {
self.queue.push(task)
} else {
--self.available
task.let()
}
return task.promise
}
signal() {
const self = internal(this)
if (self.queue.length === 0) {
++self.available
} else {
self.queue.shift().let()
}
}
// Properties
get capacity() {
const self = internal(this)
return self.capacity
}
get available() {
const self = internal(this)
return self.available
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment