sharedlist.nim 2.3 KB

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