list.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package hashmap
  2. import (
  3. "sync/atomic"
  4. "unsafe"
  5. )
  6. // List is a sorted doubly linked list.
  7. type List struct {
  8. count uintptr
  9. head *ListElement
  10. }
  11. // NewList returns an initialized list.
  12. func NewList() *List {
  13. return &List{head: &ListElement{}}
  14. }
  15. // Len returns the number of elements within the list.
  16. func (l *List) Len() int {
  17. if l == nil { // not initialized yet?
  18. return 0
  19. }
  20. return int(atomic.LoadUintptr(&l.count))
  21. }
  22. // First returns the head item of the list.
  23. func (l *List) Head() *ListElement {
  24. if l == nil { // not initialized yet?
  25. return nil
  26. }
  27. return l.head
  28. }
  29. // First returns the first item of the list.
  30. func (l *List) First() *ListElement {
  31. if l == nil { // not initialized yet?
  32. return nil
  33. }
  34. return l.head.Next()
  35. }
  36. // Add adds an item to the list and returns false if an item for the hash existed.
  37. // searchStart = nil will start to search at the head item
  38. func (l *List) Add(element *ListElement, searchStart *ListElement) (existed bool, inserted bool) {
  39. left, found, right := l.search(searchStart, element)
  40. if found != nil { // existing item found
  41. return true, false
  42. }
  43. return false, l.insertAt(element, left, right)
  44. }
  45. // AddOrUpdate adds or updates an item to the list.
  46. func (l *List) AddOrUpdate(element *ListElement, searchStart *ListElement) bool {
  47. left, found, right := l.search(searchStart, element)
  48. if found != nil { // existing item found
  49. found.setValue(element.value) // update the value
  50. return true
  51. }
  52. return l.insertAt(element, left, right)
  53. }
  54. // Cas compares and swaps the value of an item in the list.
  55. func (l *List) Cas(element *ListElement, oldValue interface{}, searchStart *ListElement) bool {
  56. _, found, _ := l.search(searchStart, element)
  57. if found == nil { // no existing item found
  58. return false
  59. }
  60. if found.casValue(oldValue, element.value) {
  61. return true
  62. }
  63. return false
  64. }
  65. func (l *List) search(searchStart *ListElement, item *ListElement) (left *ListElement, found *ListElement, right *ListElement) {
  66. if searchStart != nil && item.keyHash < searchStart.keyHash { // key would remain left from item? {
  67. searchStart = nil // start search at head
  68. }
  69. if searchStart == nil { // start search at head?
  70. left = l.head
  71. found = left.Next()
  72. if found == nil { // no items beside head?
  73. return nil, nil, nil
  74. }
  75. } else {
  76. found = searchStart
  77. }
  78. for {
  79. if item.keyHash == found.keyHash { // key already exists
  80. return nil, found, nil
  81. }
  82. if item.keyHash < found.keyHash { // new item needs to be inserted before the found value
  83. if l.head == left {
  84. return nil, nil, found
  85. }
  86. return left, nil, found
  87. }
  88. // go to next element in sorted linked list
  89. left = found
  90. found = left.Next()
  91. if found == nil { // no more items on the right
  92. return left, nil, nil
  93. }
  94. }
  95. }
  96. func (l *List) insertAt(element *ListElement, left *ListElement, right *ListElement) bool {
  97. if left == nil {
  98. //element->previous = head
  99. element.previousElement = unsafe.Pointer(l.head)
  100. //element->next = right
  101. element.nextElement = unsafe.Pointer(right)
  102. // insert at head, head-->next = element
  103. if !atomic.CompareAndSwapPointer(&l.head.nextElement, unsafe.Pointer(right), unsafe.Pointer(element)) {
  104. return false // item was modified concurrently
  105. }
  106. //right->previous = element
  107. if right != nil {
  108. if !atomic.CompareAndSwapPointer(&right.previousElement, unsafe.Pointer(l.head), unsafe.Pointer(element)) {
  109. return false // item was modified concurrently
  110. }
  111. }
  112. } else {
  113. element.previousElement = unsafe.Pointer(left)
  114. element.nextElement = unsafe.Pointer(right)
  115. if !atomic.CompareAndSwapPointer(&left.nextElement, unsafe.Pointer(right), unsafe.Pointer(element)) {
  116. return false // item was modified concurrently
  117. }
  118. if right != nil {
  119. if !atomic.CompareAndSwapPointer(&right.previousElement, unsafe.Pointer(left), unsafe.Pointer(element)) {
  120. return false // item was modified concurrently
  121. }
  122. }
  123. }
  124. atomic.AddUintptr(&l.count, 1)
  125. return true
  126. }
  127. // Delete deletes an element from the list.
  128. func (l *List) Delete(element *ListElement) {
  129. if !atomic.CompareAndSwapUintptr(&element.deleted, uintptr(0), uintptr(1)) {
  130. return // concurrent delete of the item in progress
  131. }
  132. for {
  133. left := element.Previous()
  134. right := element.Next()
  135. if left == nil { // element is first item in list?
  136. if !atomic.CompareAndSwapPointer(&l.head.nextElement, unsafe.Pointer(element), unsafe.Pointer(right)) {
  137. continue // now head item was inserted concurrently
  138. }
  139. } else {
  140. if !atomic.CompareAndSwapPointer(&left.nextElement, unsafe.Pointer(element), unsafe.Pointer(right)) {
  141. continue // item was modified concurrently
  142. }
  143. }
  144. if right != nil {
  145. atomic.CompareAndSwapPointer(&right.previousElement, unsafe.Pointer(element), unsafe.Pointer(left))
  146. }
  147. break
  148. }
  149. atomic.AddUintptr(&l.count, ^uintptr(0)) // decrease counter
  150. }