-
Notifications
You must be signed in to change notification settings - Fork 4
/
test.nim
128 lines (107 loc) · 2.96 KB
/
test.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
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
import std/osproc
import std/strutils
import std/logging
import std/atomics
import std/os
import std/macros
import balls
import cps
import loony
const
continuationCount = when defined(windows): 10_000 else: 10_000
let
threadCount = when defined(danger): countProcessors() else: 1
type
C = ref object of Continuation
addHandler newConsoleLogger()
setLogFilter:
when defined(danger):
lvlNotice
elif defined(release):
lvlInfo
else:
lvlDebug
var q: LoonyQueue[Continuation]
proc runThings() {.thread.} =
{.gcsafe.}:
while true:
var job = pop q
if job.dismissed:
break
else:
while job.running:
job = trampoline job
proc enqueue(c: C): C {.cpsMagic.} =
check not q.isNil
q.push(c)
var counter {.global.}: Atomic[int]
# try to delay a reasonable amount of time despite platform
when defined(windows):
proc noop(c: C): C {.cpsMagic.} =
sleep:
when defined(danger) and false: # Reduce cont count on windows before adding sleep
1
else:
0 # 🤔
c
else:
import posix
proc noop(c: C): C {.cpsMagic.} =
const
ns = when defined(danger): 1_000 else: 10_000
var x = Timespec(tv_sec: 0.Time, tv_nsec: ns)
var y: Timespec
if 0 != nanosleep(x, y):
fail "nanosleep fail"
c
proc doContinualThings() {.cps: C.} =
enqueue()
noop()
enqueue()
discard counter.fetchAdd(1)
template expectCounter(n: int): untyped =
## convenience
try:
check counter.load == n
except Exception:
checkpoint " counter: ", load counter
checkpoint "expected: ", n
raise
suite "loony":
block:
## creation and initialization of the queue
# Moment of truth
q = initLoonyQueue[Continuation]()
block:
## run some continuations through the queue in another thread
when defined(danger): skip "boring"
var thr: Thread[void]
counter.store 0
dumpAllocStats:
for i in 0 ..< continuationCount:
var c = whelp doContinualThings()
discard enqueue c
createThread(thr, runThings)
joinThread thr
expectCounter continuationCount
block:
## run some continuations through the queue in many threads
when not defined(danger): skip "slow"
var threads: seq[Thread[void]]
newSeq(threads, threadCount)
counter.store 0
dumpAllocStats:
debugNodeCounter:
# If `loonyDebug` is defined this will output number of nodes you started
# with - the number of nodes you end with (= non-deallocated nodes)
for i in 0 ..< continuationCount:
var c = whelp doContinualThings()
discard enqueue c
checkpoint "queued $# continuations" % [ $continuationCount ]
for thread in threads.mitems:
createThread(thread, runThings)
checkpoint "created $# threads" % [ $threadCount ]
for thread in threads.mitems:
joinThread thread
checkpoint "joined $# threads" % [ $threadCount ]
expectCounter continuationCount