github.com/tursom/GoCollections@v0.3.10/concurrent/collections/ConcurrentLinkedStack.go (about) 1 /* 2 * Copyright (c) 2022 tursom. All rights reserved. 3 * Use of this source code is governed by a GPL-3 4 * license that can be found in the LICENSE file. 5 */ 6 7 package collections 8 9 import ( 10 "github.com/tursom/GoCollections/collections" 11 "github.com/tursom/GoCollections/exceptions" 12 "github.com/tursom/GoCollections/lang" 13 "github.com/tursom/GoCollections/lang/atomic" 14 ) 15 16 type ( 17 ConcurrentLinkedStack[T lang.Object] struct { 18 lang.BaseObject 19 size atomic.Int32 20 deleted atomic.Int32 21 head *linkedStackNode[T] 22 } 23 24 linkedStackNode[T any] struct { 25 deleted bool 26 next *linkedStackNode[T] 27 value T 28 } 29 30 linkedStackIterator[T lang.Object] struct { 31 node *linkedStackNode[T] 32 stack *ConcurrentLinkedStack[T] 33 } 34 ) 35 36 func (s *ConcurrentLinkedStack[T]) String() string { 37 return collections.String[T](s) 38 } 39 40 func NewLinkedStack[T lang.Object]() *ConcurrentLinkedStack[T] { 41 return &ConcurrentLinkedStack[T]{} 42 } 43 44 func (s *ConcurrentLinkedStack[T]) Iterator() collections.Iterator[T] { 45 return s.MutableIterator() 46 } 47 48 func (s *ConcurrentLinkedStack[T]) Push(element T) exceptions.Exception { 49 s.push(element) 50 return nil 51 } 52 53 func (s *ConcurrentLinkedStack[T]) PushAndGetNode(element T) collections.StackNode[T] { 54 return &linkedStackIterator[T]{ 55 node: s.push(element), 56 stack: s, 57 } 58 } 59 60 func (s *ConcurrentLinkedStack[T]) push(element T) *linkedStackNode[T] { 61 newNode := &linkedStackNode[T]{value: element, next: s.head} 62 for !atomic.CompareAndSwapPointer(&s.head, newNode.next, newNode) { 63 newNode.next = s.head 64 } 65 s.size.Add(1) 66 return newNode 67 } 68 69 func (s *ConcurrentLinkedStack[T]) Pop() (T, exceptions.Exception) { 70 node := s.head 71 for node != nil && (!atomic.CompareAndSwapPointer(&s.head, node, node.next) || node.deleted) { 72 node = s.head 73 } 74 if node == nil { 75 return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil) 76 } 77 78 s.size.Add(-1) 79 return node.value, nil 80 } 81 82 // CleanDeleted tell stack that may clean deleted nodes 83 func (s *ConcurrentLinkedStack[T]) CleanDeleted() { 84 if s.deleted.Load() <= s.size.Load() { 85 return 86 } 87 s.deleted.Store(0) 88 node := &s.head 89 for node != nil && *node != nil { 90 if (*node).deleted { 91 atomic.CompareAndSwapPointer(node, *node, (*node).next) 92 } else { 93 node = &(*node).next 94 } 95 } 96 } 97 98 func (s *ConcurrentLinkedStack[T]) Size() int { 99 return int(s.size.Load()) 100 } 101 102 func (s *ConcurrentLinkedStack[T]) IsEmpty() bool { 103 return s.head == nil 104 } 105 106 func (s *ConcurrentLinkedStack[T]) Contains(element T) bool { 107 return collections.Contains[T](s, element) 108 } 109 110 func (s *ConcurrentLinkedStack[T]) ContainsAll(c collections.Collection[T]) bool { 111 return collections.ContainsAll[T](s, c) 112 } 113 114 func (s *ConcurrentLinkedStack[T]) Add(element T) bool { 115 exception := s.Push(element) 116 exceptions.Print(exception) 117 return exception == nil 118 } 119 120 func (s *ConcurrentLinkedStack[T]) Remove(element T) exceptions.Exception { 121 return collections.Remove[T](s, element) 122 } 123 124 func (s *ConcurrentLinkedStack[T]) AddAll(c collections.Collection[T]) bool { 125 return collections.AddAll[T](s, c) 126 } 127 128 func (s *ConcurrentLinkedStack[T]) RemoveAll(c collections.Collection[T]) bool { 129 return collections.RemoveAll[T](s, c) 130 } 131 132 func (s *ConcurrentLinkedStack[T]) RetainAll(c collections.Collection[T]) bool { 133 return collections.RetainAll[T](s, c) 134 } 135 136 func (s *ConcurrentLinkedStack[T]) Clear() { 137 s.head = nil 138 s.size.Store(0) 139 } 140 141 func (s *ConcurrentLinkedStack[T]) MutableIterator() collections.MutableIterator[T] { 142 return &linkedStackIterator[T]{s.head, nil} 143 } 144 145 func (i *linkedStackIterator[T]) HasNext() bool { 146 return i.node.next != nil 147 } 148 149 func (i *linkedStackIterator[T]) Next() (T, exceptions.Exception) { 150 if i.node == nil { 151 return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil) 152 } 153 value := i.node.value 154 i.node = i.node.next 155 return value, nil 156 } 157 158 func (i *linkedStackIterator[T]) Remove() exceptions.Exception { 159 if i.node == nil { 160 return exceptions.NewIndexOutOfBound("", nil) 161 } 162 i.node.deleted = true 163 i.node = i.node.next 164 i.stack.size.Add(-1) 165 i.stack.deleted.Add(1) 166 i.stack.CleanDeleted() 167 return nil 168 } 169 170 func (i *linkedStackIterator[T]) Get() (T, exceptions.Exception) { 171 return i.node.value, nil 172 } 173 174 func (i *linkedStackIterator[T]) Set(value T) exceptions.Exception { 175 i.node.value = value 176 return nil 177 } 178 179 func (i *linkedStackIterator[T]) RemoveAndGet() (T, exceptions.Exception) { 180 i.node.deleted = true 181 return i.node.value, nil 182 }