sharedlist.nim 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Shared list support.
  10. {.push stackTrace:off.}
  11. import
  12. locks
  13. const
  14. ElemsPerNode = 100
  15. type
  16. SharedListNode[A] = ptr object
  17. next: SharedListNode[A]
  18. dataLen: int
  19. d: array[ElemsPerNode, A]
  20. SharedList*[A] = object ## generic shared list
  21. head, tail: SharedListNode[A]
  22. lock*: Lock
  23. template withLock(t, x: untyped) =
  24. acquire(t.lock)
  25. x
  26. release(t.lock)
  27. proc iterAndMutate*[A](x: var SharedList[A]; action: proc(x: A): bool) =
  28. ## iterates over the list. If 'action' returns true, the
  29. ## current item is removed from the list.
  30. withLock(x):
  31. var n = x.head
  32. while n != nil:
  33. var i = 0
  34. while i < n.dataLen:
  35. # action can add new items at the end, so release the lock:
  36. release(x.lock)
  37. if action(n.d[i]):
  38. acquire(x.lock)
  39. let t = x.tail
  40. n.d[i] = t.d[t.dataLen]
  41. dec t.dataLen
  42. else:
  43. acquire(x.lock)
  44. inc i
  45. n = n.next
  46. iterator items*[A](x: var SharedList[A]): A =
  47. withLock(x):
  48. var it = x.head
  49. while it != nil:
  50. for i in 0..it.dataLen-1:
  51. yield it.d[i]
  52. it = it.next
  53. proc add*[A](x: var SharedList[A]; y: A) =
  54. withLock(x):
  55. var node: SharedListNode[A]
  56. if x.tail == nil or x.tail.dataLen == ElemsPerNode:
  57. node = cast[type node](allocShared0(sizeof(node[])))
  58. node.next = x.tail
  59. x.tail = node
  60. if x.head == nil: x.head = node
  61. else:
  62. node = x.tail
  63. node.d[node.dataLen] = y
  64. inc(node.dataLen)
  65. proc init*[A](t: var SharedList[A]) =
  66. initLock t.lock
  67. t.head = nil
  68. t.tail = nil
  69. proc clear*[A](t: var SharedList[A]) =
  70. withLock(t):
  71. var it = t.head
  72. while it != nil:
  73. let nxt = it.next
  74. deallocShared(it)
  75. it = nxt
  76. t.head = nil
  77. t.tail = nil
  78. proc deinitSharedList*[A](t: var SharedList[A]) =
  79. clear(t)
  80. deinitLock t.lock
  81. proc initSharedList*[A](): SharedList[A] {.deprecated.} =
  82. ## Deprecated. Use `init` instead.
  83. ## This is not posix compliant, may introduce undefined behavior.
  84. initLock result.lock
  85. result.head = nil
  86. result.tail = nil
  87. {.pop.}