1 | function create-pool (n)
|
2 | T = this
|
3 | n = Math.floor n
|
4 | throw '.createPool( num ): number of threads must be a Number > 0' unless n > 0
|
5 |
|
6 | pool = []
|
7 | idle-threads = []
|
8 | q = { first: null, last: null, length: 0 }
|
9 | pool-object = {
|
10 | on: on-event
|
11 | load: pool-load
|
12 | destroy: destroy
|
13 | pending-jobs: get-pending-jobs
|
14 | idle-threads: get-idle-threads
|
15 | total-threads: get-num-threads
|
16 | any: { eval: eval-any, emit: emit-any }
|
17 | all: { eval: eval-all, emit: emit-all }
|
18 | }
|
19 |
|
20 | try
|
21 | while n-- => pool[n] = idle-threads[n] = T.create!
|
22 | catch e
|
23 | destroy \rudely
|
24 | throw e
|
25 |
|
26 | return pool-object
|
27 |
|
28 |
|
29 |
|
30 | function pool-load (path, cb)
|
31 | i = pool.length
|
32 | while i--
|
33 | pool[i].load path, cb
|
34 | return
|
35 |
|
36 | function next-job (t)
|
37 | job = q-pull!
|
38 | if job
|
39 | if job.type is 1
|
40 | t.eval job.src-text-or-event-type, (e, d) ->
|
41 | next-job t
|
42 | f = job.cb-or-data
|
43 | if typeof f is \function
|
44 | try
|
45 | f.call t, e, d
|
46 | catch e
|
47 | return e
|
48 | else
|
49 | t.emit job.src-text-or-event-type, f
|
50 | else if job.type is 2
|
51 | t.emit job.src-text-or-event-type, job.cb-or-data
|
52 | next-job t
|
53 | else
|
54 | idle-threads.push t
|
55 | return
|
56 |
|
57 | function q-push (src-text-or-event-type, cb-or-data, type)
|
58 | job = { src-text-or-event-type, cb-or-data, type, next: null }
|
59 | if q.last
|
60 | q.last = q.last.next = job
|
61 | else
|
62 | q.first = q.last = job
|
63 | q.length++
|
64 | return
|
65 |
|
66 | function q-pull
|
67 | job = q.first
|
68 | if job
|
69 | if q.last is job then q.first = q.last = null else q.first = job.next
|
70 | q.length--
|
71 | return job
|
72 |
|
73 | function eval-any (src, cb)
|
74 | q-push src, cb, 1
|
75 | next-job idle-threads.pop! if idle-threads.length
|
76 | return pool-object
|
77 |
|
78 | function eval-all (src, cb)
|
79 | pool.for-each (v, i, o) -> v.eval src, cb
|
80 | return pool-object
|
81 |
|
82 | function emit-any (event, data)
|
83 | q-push event, data, 2
|
84 | next-job idle-threads.pop! if idle-threads.length
|
85 | return pool-object
|
86 |
|
87 | function emit-all (event, data)
|
88 | pool.for-each (v, i, o) -> v.emit event, data
|
89 | return pool-object
|
90 |
|
91 | function on-event (event, cb)
|
92 | pool.for-each (v, i, o) -> v.on event, cb
|
93 | return this
|
94 |
|
95 | function destroy (rudely)
|
96 | err = -> throw 'This thread pool has been destroyed'
|
97 | be-nice = -> if q.length then setTimeout be-nice, 666 else be-rude!
|
98 | be-rude = ->
|
99 | q.length = 0
|
100 | q.first = null
|
101 | pool.for-each (v, i, o) -> v.destroy!
|
102 | pool-object.eval = pool-object.total-threads = pool-object.idle-threads =
|
103 | pool-object.pendingJobs = pool-object.destroy = err
|
104 | if rudely then be-rude! else be-nice!
|
105 | return
|
106 |
|
107 | function get-num-threads => pool.length
|
108 | function get-idle-threads => idle-threads.length
|
109 | function get-pending-jobs => q.length
|