Skip to content

Commit

Permalink
Slice a copy of outstanding callbacks.
Browse files Browse the repository at this point in the history
Take a slice of the callbacks before invoking the turnstile, instead of
calling all callbacks after invoking the turnstile. That's a race
condition because the callback could have been added after the turnstile
was entered.

Closes #19.
  • Loading branch information
flatheadmill committed Jun 6, 2014
1 parent 152fd98 commit f743452
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
26 changes: 18 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
var __slice = [].slice

module.exports = function (procedure, subsequent) {
var running, waiting, callbacks = []
var running, waiting, callbacks = { queue: [] }
function run (callback) {
if (callback) {
callbacks.push(callback)
callbacks.queue.push(callback)
}
if (!running) {
running = true
callbacks.next = callbacks.queue.splice(0, callbacks.queue.length)
if (subsequent) {
callbacks.next.unshift(subsequent)
}
try {
procedure(function () {
var vargs = __slice.call(arguments)
running = false
subsequent.apply(null, arguments)
while (callbacks.length) {
callbacks.shift().apply(null, arguments)
}
callbacks.next.splice(0, callbacks.next.length).forEach(function (callback) {
callback.apply(null, vargs)
})
if (waiting) {
waiting = false
run()
}
})
} catch (e) {
} catch (error) {
running = false
subsequent(e)
if (callbacks.next.length) {
callbacks.next.forEach(function (callback) { callback.call(null, error) })
} else {
throw error
}
}
} else {
waiting = true
Expand Down
3 changes: 3 additions & 0 deletions release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Issue by Issue

* Slice a copy of outstanding callbacks. #19.
16 changes: 13 additions & 3 deletions t/turnstile/throw.t.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
require('proof')(1, function (step, assert) {
var results = [], pause
var turnstile = require('../..')(function (callback) {
require('proof')(2, function (step, assert) {
var results = [], turnstile
turnstile = require('../..')(function (callback) {
throw new Error('abend')
}, function (error) {
assert(error.message, 'abend', 'caught')
})
turnstile()
turnstile = require('../..')(function (callback) {
callback(new Error('abend'))
})
try {
turnstile(function (error) {
throw error
})
} catch (error) {
assert(error.message, 'abend', 'uncaught')
}
})

0 comments on commit f743452

Please sign in to comment.