sharedlist.nim 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. ##
  11. ## Unstable API.
  12. {.push stackTrace: off.}
  13. import
  14. locks
  15. const
  16. ElemsPerNode = 100
  17. type
  18. SharedListNode[A] = ptr object
  19. next: SharedListNode[A]
  20. dataLen: int
  21. d: array[ElemsPerNode, A]
  22. SharedList*[A] = object ## generic shared list
  23. head, tail: SharedListNode[A]
  24. lock*: Lock
  25. template withLock(t, x: untyped) =
  26. acquire(t.lock)
  27. x
  28. release(t.lock)
  29. proc iterAndMutate*[A](x: var SharedList[A]; action: proc(x: A): bool) =
  30. ## Iterates over the list. If `action` returns true, the
  31. ## current item is removed from the list.
  32. ##
  33. ## .. warning:: It may not preserve the element order after some modifications.
  34. withLock(x):
  35. var n = x.head
  36. while n != nil:
  37. var i = 0
  38. while i < n.dataLen:
  39. # action can add new items at the end, so release the lock:
  40. release(x.lock)
  41. if action(n.d[i]):
  42. acquire(x.lock)
  43. let t = x.tail
  44. dec t.dataLen # TODO considering t.dataLen == 0,
  45. # probably the module should be refactored using doubly linked lists
  46. n.d[i] = t.d[t.dataLen]
  47. else:
  48. acquire(x.lock)
  49. inc i
  50. n = n.next
  51. iterator items*[A](x: var SharedList[A]): A =
  52. withLock(x):
  53. var it = x.head
  54. while it != nil:
  55. for i in 0..it.dataLen-1:
  56. yield it.d[i]
  57. it = it.next
  58. proc add*[A](x: var SharedList[A]; y: A) =
  59. withLock(x):
  60. var node: SharedListNode[A]
  61. if x.tail == nil:
  62. node = cast[typeof node](allocShared0(sizeof(node[])))
  63. x.tail = node
  64. x.head = node
  65. elif x.tail.dataLen == ElemsPerNode:
  66. node = cast[typeof node](allocShared0(sizeof(node[])))
  67. x.tail.next = node
  68. x.tail = node
  69. else:
  70. node = x.tail
  71. node.d[node.dataLen] = y
  72. inc(node.dataLen)
  73. proc init*[A](t: var SharedList[A]) =
  74. initLock t.lock
  75. t.head = nil
  76. t.tail = nil
  77. proc clear*[A](t: var SharedList[A]) =
  78. withLock(t):
  79. var it = t.head
  80. while it != nil:
  81. let nxt = it.next
  82. deallocShared(it)
  83. it = nxt
  84. t.head = nil
  85. t.tail = nil
  86. proc deinitSharedList*[A](t: var SharedList[A]) =
  87. clear(t)
  88. deinitLock t.lock
  89. {.pop.}