summary refs log tree commit diff stats
path: root/tests/isolate/tisolated_lock.nim
blob: 312abf0f62b061fa14fa357e312b8490fda055b2 (plain) (blame)
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
discard """
  cmd: "nim $target --threads:on $options $file"
  action: "compile"
"""

import std / [os, locks, atomics, isolation]

type
  MyList {.acyclic.} = ref object
    data: string
    next: Isolated[MyList]

template withMyLock*(a: Lock, body: untyped) =
  acquire(a)
  {.gcsafe.}:
    try:
      body
    finally:
      release(a)

var head: Isolated[MyList]
var headL: Lock

var shouldStop: Atomic[bool]

initLock headL

proc send(x: sink string) =
  withMyLock headL:
    head = isolate MyList(data: x, next: move head)

proc worker() {.thread.} =
  var workItem = MyList(nil)
  var echoed = 0
  while true:
    withMyLock headL:
      var h = extract head
      if h != nil:
        workItem = h
        # workitem is now isolated:
        head = move h.next
      else:
        workItem = nil
    # workItem is isolated, so we can access it outside
    # the lock:
    if workItem.isNil:
      if shouldStop.load:
        break
      else:
        # give producer time to breath:
        os.sleep 30
    else:
      if echoed < 100:
        echo workItem.data
      inc echoed

var thr: Thread[void]
createThread(thr, worker)

send "abc"
send "def"
for i in 0 ..< 10_000:
  send "xzy"
  send "zzz"
shouldStop.store true

joinThread(thr)