forked from coordcn/luaio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparallel.lua
129 lines (109 loc) · 2.81 KB
/
parallel.lua
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
local co_create = coroutine.create
local co_yield = coroutine.yield
local co_running = coroutine.running
local co_resume = coroutine.resume
local co_status = coroutine.status
local unpack = table.unpack
local parallel = {}
function parallel.all(funcs, limit)
if type(funcs) ~= 'table' then
error('parallel.all(funcs, limit) error: funcs must be table(array[function])')
end
local num = #funcs
if limit == nil then limit = num end
if type(limit) ~= 'number' then
error('parallel.all(funcs, limit) error: limit must be number')
end
if limit > num then limit = num end
local parent_co = co_running()
local results = {}
local index = 0
local flag = false
local completed = 0
local running = 0
function collect(index, ...)
results[index] = {...}
completed = completed + 1
if completed == running then
co_resume(parent_co)
end
end
while true do
while running < limit do
index = index + 1
local co = co_create(function(func, index)
collect(index, func())
end)
co_resume(co, funcs[index], index)
if co_status(co) == 'dead' then
completed = completed - 1
else
running = running + 1
end
if index == num then
flag = true
break
end
end
if running > 0 then co_yield() end
if flag then break end
running = 0
completed = 0
end
return results
end
function parallel.map(args, func, limit)
if type(args) ~= 'table' then
error('parallel.map(args, func, limit) error: args must be table(array[array])')
end
if type(func) ~= 'function' then
error('parallel.map(args, func, limit) error: fun must be function')
end
local num = #args
if limit == nil then limit = num end
if type(limit) ~= 'number' then
error('parallel.map(args, func, limit) error: limit must be number')
end
if limit > num then limit = num end
local parent_co = co_running()
local results = {}
local index = 0
local flag = false
local completed = 0
local running = 0
function collect(index, ...)
results[index] = {...}
completed = completed + 1
if completed == running then
co_resume(parent_co)
end
end
while true do
while running < limit do
index = index + 1
local co = co_create(function(arg, index)
if type(arg) == 'table' then
collect(index, func(unpack(arg)))
else
collect(index, func(arg))
end
end)
co_resume(co, args[index], index)
if co_status(co) == 'dead' then
completed = completed - 1
else
running = running + 1
end
if index == num then
flag = true
break
end
end
if running > 0 then co_yield() end
if flag then break end
running = 0
completed = 0
end
return results
end
return parallel