-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconcurrency.js
145 lines (123 loc) · 3.42 KB
/
concurrency.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// usage :
// C.add(asyncFuncProtype,...args)
// C.wait().then(()=>{console.log("all done")})
// asyncFuncProtype must be a async func,otherwise there might be uncentain error.
// look demo for more detail.
const C = (function () {
let maxRunning = 5
let currentRunning = 0
let result = []
let iterator = {
queue: [], cursor: -1,
add: function (asyncFunc, ...args) {
this.queue.push({ f: asyncFunc, args: args })
},
reset: function () {
this.cursor = -1; this.queue = []
},
nextCursor: function () {
let c = ++this.cursor
if (c > iterator.queue.length - 1) {
--this.cursor
return null
}
return c
},
next: function () {
let c = this.nextCursor()
return c === null ? null : iterator.queue[c]
},
}
async function work() {
for (; ;) {
let o = iterator.next()
if (!o) return
let answer = await o.f(...o.args)
result.push({
"args": o.args,
"answer": answer
})
}
}
function worker() {
work().then(() => {
currentRunning--
console.log("die")
})
}
function newJob() {
if (currentRunning >= maxRunning) return
console.log("new Worker")
currentRunning++
worker()
}
return {
// add async function and args.
//
add: function (asyncFunc, ...args) {
iterator.add(asyncFunc, ...args)
newJob()
},
wait: async function () {
for (; ;) {
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
})
if (currentRunning == 0) {
break
}
}
},
// call C.reset() to init C's internal iterator.
// It makes sure that a new batch of async tasks work normally.
reset: function () {
iterator.reset()
result = []
},
getResult: function () {
return result
},
// set max concurrency
setMaxRunning: function (num) {
maxRunning = num
},
isDone: function () {
return currentRunning == 0
}
}
})()
function demo() {
function timeToPrint(t, ex = "") {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(t, ex)
resolve()
}, t)
})
}
function timeToPush(t, ex = "") {
setTimeout(() => {
C.add(timeToPrint, t, ex)
}, t)
}
setTimeout(() => {
for (let i = 1; i < 100; i++) {
let t = i
C.add(timeToPush, t, "from 1")
}
}, 1000)
setTimeout(() => {
for (let i = 1; i < 100; i = i + 5) {
let t = i
C.add(timeToPush, t, "from 2")
}
}, 5000)
setTimeout(() => {
for (let i = 1; i < 100; i = i + 3) {
let t = i
C.add(timeToPush, t, "from 3")
}
}, 10000)
}