github.com/ronaksoft/rony@v0.16.26-0.20230807065236-1743dbfe6959/tools/linked_list.go (about) 1 package tools 2 3 import ( 4 "fmt" 5 "strings" 6 "sync" 7 ) 8 9 /* 10 Creation Time: 2019 - Jun - 20 11 Created by: (ehsan) 12 Maintainers: 13 1. Ehsan N. Moosa (E2) 14 Auditor: Ehsan N. Moosa (E2) 15 Copyright Ronak Software Group 2020 16 */ 17 18 var ( 19 nodePool sync.Pool 20 ) 21 22 func acquireNode() *Node { 23 n, ok := nodePool.Get().(*Node) 24 if !ok { 25 return &Node{} 26 } 27 28 return n 29 } 30 31 func releaseNode(n *Node) { 32 *n = Node{} 33 nodePool.Put(n) 34 } 35 36 type Node struct { 37 next *Node 38 prev *Node 39 data interface{} 40 } 41 42 func (n Node) GetData() interface{} { 43 return n.data 44 } 45 46 type LinkedList struct { 47 lock sync.RWMutex 48 head *Node 49 tail *Node 50 size int32 51 } 52 53 func NewLinkedList() *LinkedList { 54 return &LinkedList{} 55 } 56 57 func (ll *LinkedList) Append(data interface{}) { 58 ll.lock.Lock() 59 ll.size += 1 60 n := acquireNode() 61 n.data = data 62 if ll.tail == nil { 63 ll.tail, ll.head = n, n 64 } else { 65 o := ll.tail 66 ll.tail = n 67 ll.tail.prev = o 68 o.next = ll.tail 69 } 70 ll.lock.Unlock() 71 } 72 73 func (ll *LinkedList) Prepend(data interface{}) { 74 ll.lock.Lock() 75 ll.size += 1 76 n := acquireNode() 77 n.data = data 78 if ll.head == nil { 79 ll.tail, ll.head = n, n 80 } else { 81 o := ll.head 82 ll.head = n 83 ll.head.next = o 84 o.prev = ll.head 85 } 86 ll.lock.Unlock() 87 } 88 89 func (ll *LinkedList) Size() int32 { 90 ll.lock.RLock() 91 n := ll.size 92 ll.lock.RUnlock() 93 94 return n 95 } 96 97 func (ll *LinkedList) Head() *Node { 98 return ll.head 99 } 100 101 func (ll *LinkedList) PickHeadData() interface{} { 102 ll.lock.Lock() 103 if ll.head == nil { 104 ll.lock.Unlock() 105 106 return nil 107 } 108 109 n := ll.head 110 if ll.head.next != nil { 111 ll.head = ll.head.next 112 ll.head.prev = nil 113 } else { 114 ll.head, ll.tail = nil, nil 115 } 116 ll.size-- 117 ll.lock.Unlock() 118 data := n.data 119 releaseNode(n) 120 121 return data 122 } 123 124 func (ll *LinkedList) Tail() *Node { 125 return ll.tail 126 } 127 128 func (ll *LinkedList) PickTailData() interface{} { 129 ll.lock.Lock() 130 if ll.tail == nil { 131 ll.lock.Unlock() 132 133 return nil 134 } 135 n := ll.tail 136 if ll.tail.prev != nil { 137 ll.tail = ll.tail.prev 138 ll.tail.next = nil 139 } else { 140 ll.head, ll.tail = nil, nil 141 } 142 ll.size -= 1 143 ll.lock.Unlock() 144 data := n.data 145 releaseNode(n) 146 147 return data 148 } 149 150 func (ll *LinkedList) Get(index int32) (n *Node) { 151 ll.lock.RLock() 152 if index < ll.size<<1 { 153 n = ll.head 154 for index > 0 { 155 n = n.next 156 index-- 157 } 158 } else { 159 n = ll.tail 160 for index > 0 { 161 n = n.prev 162 index-- 163 } 164 } 165 ll.lock.RUnlock() 166 167 return n 168 } 169 170 func (ll *LinkedList) RemoveAt(index int32) { 171 n := ll.Get(index) 172 ll.lock.Lock() 173 if n.next != nil { 174 n.next.prev = n.prev 175 } 176 if n.prev != nil { 177 n.prev.next = n.next 178 } 179 ll.size-- 180 ll.lock.Unlock() 181 } 182 183 func (ll *LinkedList) Reset() { 184 for ll.PickHeadData() != nil { 185 } 186 } 187 188 func (ll *LinkedList) String() string { 189 sb := strings.Builder{} 190 n := ll.head 191 idx := 0 192 for n != nil { 193 sb.WriteString(fmt.Sprintf("%d. %v\n", idx, n.data)) 194 n = n.next 195 idx++ 196 } 197 198 return sb.String() 199 }