-
Notifications
You must be signed in to change notification settings - Fork 17
/
threadpool.nim
90 lines (64 loc) · 1.76 KB
/
threadpool.nim
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
#
# Simple test of a naive threadpool for scheduling CPS threads. This demo
# creates many 'threads' scheduled on all available CPUs in the system
#
# nim r --gc:arc --threads:on --threadanalysis:off stash/threadpool.nim
#
import cps, math, std/locks, deques, cpuinfo
###########################################################################
# Implementation of the thread pool
###########################################################################
type Cont = ref object of Continuation
type Pool = ref object
work: Deque[Cont]
lock: Lock
proc newPool(): Pool =
result = Pool()
initLock(result.lock)
var pool = newPool()
proc doWork(pool: Pool) {.thread.} =
while true:
pool.lock.acquire
if pool.work.len == 0:
pool.lock.release
return
var c = Continuation: pool.work.popFirst
pool.lock.release
if c.dismissed:
break
else:
c = trampoline c
proc work(nThreads: int) =
var threads: seq[Thread[Pool]]
newSeq(threads, nThreads)
for i in 0..<nThreads:
createThread(threads[i], doWork, pool)
joinThreads(threads)
proc jield(c: Cont): Cont {.cpsMagic.} =
if c != nil:
pool.lock.acquire
pool.work.addLast(c)
pool.lock.release
###########################################################################
# Main code
###########################################################################
var L: Lock
initLock L
proc slow(id: int, n: float) {.cps:Cont.} =
var i, j, b: float
while i < n:
i += 1
j = 0
while j < 1_000:
j += 0.01
b += sin(i) + cos(j)
jield()
withLock L:
echo id, ": ", b
when defined(gcArc):
for i in 1..32:
pool.work.addLast:
whelp slow(i, 4)
work(countProcessors())
else:
echo "this example doesn't work outside --gc:arc"