summary refs log tree commit diff stats
path: root/lib/pure/collections/sharedlist.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-03-28 02:14:54 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-03-28 02:26:38 +0200
commit878679fa3f78d69042c9a56977b3d032791b7a47 (patch)
tree43a9cfe6d99e132fc873a93d04fb83b70617424c /lib/pure/collections/sharedlist.nim
parente97d640ce8a8f16112a3e17241ed89c993f83fee (diff)
downloadNim-878679fa3f78d69042c9a56977b3d032791b7a47.tar.gz
added missing file
Diffstat (limited to 'lib/pure/collections/sharedlist.nim')
-rw-r--r--lib/pure/collections/sharedlist.nim95
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/pure/collections/sharedlist.nim b/lib/pure/collections/sharedlist.nim
new file mode 100644
index 000000000..e93ceb02f
--- /dev/null
+++ b/lib/pure/collections/sharedlist.nim
@@ -0,0 +1,95 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Shared list support.
+
+{.push stackTrace:off.}
+
+import
+  locks
+
+const
+  ElemsPerNode = 100
+
+type
+  SharedListNode[A] = ptr object
+    next: SharedListNode[A]
+    dataLen: int
+    d: array[ElemsPerNode, A]
+
+  SharedList*[A] = object ## generic shared list
+    head, tail: SharedListNode[A]
+    lock*: Lock
+
+template withLock(t, x: untyped) =
+  acquire(t.lock)
+  x
+  release(t.lock)
+
+proc iterAndMutate*[A](x: var SharedList[A]; action: proc(x: A): bool) =
+  ## iterates over the list. If 'action' returns true, the
+  ## current item is removed from the list.
+  withLock(x):
+    var n = x.head
+    while n != nil:
+      var i = 0
+      while i < n.dataLen:
+        # action can add new items at the end, so release the lock:
+        release(x.lock)
+        if action(n.d[i]):
+          acquire(x.lock)
+          let t = x.tail
+          n.d[i] = t.d[t.dataLen]
+          dec t.dataLen
+        else:
+          acquire(x.lock)
+          inc i
+      n = n.next
+
+iterator items*[A](x: var SharedList[A]): A =
+  withLock(x):
+    var it = x.head
+    while it != nil:
+      for i in 0..it.dataLen-1:
+        yield it.d[i]
+      it = it.next
+
+proc add*[A](x: var SharedList[A]; y: A) =
+  withLock(x):
+    var node: SharedListNode[A]
+    if x.tail == nil or x.tail.dataLen == ElemsPerNode:
+      node = cast[type node](allocShared0(sizeof(node[])))
+      node.next = x.tail
+      x.tail = node
+      if x.head == nil: x.head = node
+    else:
+      node = x.tail
+    node.d[node.dataLen] = y
+    inc(node.dataLen)
+
+proc initSharedList*[A](): SharedList[A] =
+  initLock result.lock
+  result.head = nil
+  result.tail = nil
+
+proc clear*[A](t: var SharedList[A]) =
+  withLock(t):
+    var it = t.head
+    while it != nil:
+      let nxt = it.next
+      deallocShared(it)
+      it = nxt
+    t.head = nil
+    t.tail = nil
+
+proc deinitSharedList*[A](t: var SharedList[A]) =
+  clear(t)
+  deinitLock t.lock
+
+{.pop.}