1 | const assert = require('assert')
|
2 | const events = require('events')
|
3 | const Isochronous = require('isochronous')
|
4 | const isRunning = require('is-running')
|
5 |
|
6 | class Killer extends events.EventEmitter {
|
7 | constructor (interval) {
|
8 | super()
|
9 | this._isochronous = new Isochronous(interval, true, async () => {
|
10 | let i = 0, I = this._pids.length
|
11 | while (i < I) {
|
12 | const pid = this._pids[i]
|
13 | if (!isRunning(pid)) {
|
14 | this.emit('killed', pid)
|
15 | this._pids.splice(i, 1)
|
16 | I--
|
17 | } else {
|
18 | i++
|
19 | }
|
20 | }
|
21 | if (this._pids.length == 0) {
|
22 | this._clean()
|
23 | }
|
24 | await this._unlatched
|
25 | })
|
26 | this.destroyed = false
|
27 | this._pids = []
|
28 | this._exited = {}
|
29 | this._clean()
|
30 | }
|
31 |
|
32 | _clean () {
|
33 | this._unlatched = new Promise(resolve => this._latch = resolve)
|
34 | }
|
35 |
|
36 | run () {
|
37 | return this._isochronous.start()
|
38 | }
|
39 |
|
40 | exited (pid) {
|
41 | assert(this._pids.filter(p => p == pid).length == 0)
|
42 | delete this._exited[pid]
|
43 | }
|
44 |
|
45 | exit (pid) {
|
46 | assert(!this.destroyed)
|
47 | if (this._exited[pid] == null) {
|
48 | this._exited[pid] = pid
|
49 | this._pids.push(pid)
|
50 | this._latch.call()
|
51 | }
|
52 | }
|
53 |
|
54 | destroy () {
|
55 | if (!this.destroyed) {
|
56 | this.destroyed = true
|
57 | this._isochronous.stop()
|
58 | this._latch.call()
|
59 | }
|
60 | }
|
61 | }
|
62 |
|
63 | module.exports = Killer
|