GoCollections/collections/ConcurrentLinkedStack.go

92 lines
2.3 KiB
Go
Raw Normal View History

2021-05-22 17:10:26 +08:00
package collections
import (
"github.com/tursom/GoCollections/exceptions"
2022-03-21 11:02:41 +08:00
"github.com/tursom/GoCollections/lang"
2021-05-22 17:10:26 +08:00
"sync/atomic"
"unsafe"
)
2022-03-21 11:02:41 +08:00
type ConcurrentLinkedStack[T any] struct {
2022-03-23 10:15:18 +08:00
lang.BaseObject
2022-03-21 11:02:41 +08:00
head *concurrentLinkedStackNode[T]
2021-05-22 17:10:26 +08:00
p *unsafe.Pointer
}
2022-03-21 11:02:41 +08:00
func (c ConcurrentLinkedStack[T]) String() string {
return String[T](c)
2021-05-22 17:10:26 +08:00
}
2022-03-21 11:02:41 +08:00
type concurrentLinkedStackNode[T any] struct {
value T
next *concurrentLinkedStackNode[T]
2021-05-22 17:10:26 +08:00
}
2022-03-21 11:02:41 +08:00
type concurrentLinkedStackIterator[T any] struct {
node *concurrentLinkedStackNode[T]
prev *concurrentLinkedStackNode[T]
2021-05-22 17:10:26 +08:00
}
2022-03-21 11:02:41 +08:00
func NewConcurrentLinkedStack[T any]() *ConcurrentLinkedStack[T] {
head := &concurrentLinkedStackNode[T]{}
2022-03-23 10:15:18 +08:00
return &ConcurrentLinkedStack[T]{lang.NewBaseObject(), head, (*unsafe.Pointer)(unsafe.Pointer(&head.next))}
2021-05-22 17:10:26 +08:00
}
2022-03-21 11:02:41 +08:00
func (c ConcurrentLinkedStack[T]) Iterator() Iterator[T] {
2021-05-22 17:10:26 +08:00
return c.MutableIterator()
}
2022-03-21 11:02:41 +08:00
func (c *ConcurrentLinkedStack[T]) Push(element T) exceptions.Exception {
newNode := &concurrentLinkedStackNode[T]{element, c.head.next}
2021-05-22 17:10:26 +08:00
np := unsafe.Pointer(newNode)
2022-03-21 11:02:41 +08:00
for !atomic.CompareAndSwapPointer(c.p, unsafe.Pointer(&*newNode.next), np) {
2021-05-22 17:10:26 +08:00
}
return nil
}
2022-03-21 11:02:41 +08:00
func (c *ConcurrentLinkedStack[T]) Pop() (T, exceptions.Exception) {
2021-05-22 17:10:26 +08:00
next := c.head.next
if next == nil {
2022-03-21 11:02:41 +08:00
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
2021-05-22 17:10:26 +08:00
}
p := (*unsafe.Pointer)(unsafe.Pointer(&c.head.next))
2022-03-21 11:02:41 +08:00
if !atomic.CompareAndSwapPointer(p, unsafe.Pointer(&*next), unsafe.Pointer(&*next.next)) {
2021-05-22 17:10:26 +08:00
next = c.head.next
if next == nil {
2022-03-21 11:02:41 +08:00
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
2021-05-22 17:10:26 +08:00
}
}
return next.value, nil
}
2022-03-21 11:02:41 +08:00
func (c *ConcurrentLinkedStack[T]) MutableIterator() MutableIterator[T] {
return &concurrentLinkedStackIterator[T]{c.head, nil}
2021-05-22 17:10:26 +08:00
}
2022-03-21 11:02:41 +08:00
func (c *concurrentLinkedStackIterator[T]) HasNext() bool {
2021-05-22 17:10:26 +08:00
return c.node.next != nil
}
2022-03-21 11:02:41 +08:00
func (c *concurrentLinkedStackIterator[T]) Next() (T, exceptions.Exception) {
2021-05-22 17:10:26 +08:00
c.prev = c.node
c.node = c.node.next
if c.node == nil {
2022-03-21 11:02:41 +08:00
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
2021-05-22 17:10:26 +08:00
}
return c.node.value, nil
}
2022-03-21 11:02:41 +08:00
func (c *concurrentLinkedStackIterator[T]) Remove() exceptions.Exception {
2021-05-22 17:10:26 +08:00
if c.node == nil {
2022-03-21 11:02:41 +08:00
return exceptions.NewIndexOutOfBound("", nil)
2021-05-22 17:10:26 +08:00
}
next := c.node.next
p := (*unsafe.Pointer)(unsafe.Pointer(&c.prev.next))
2022-03-21 11:02:41 +08:00
atomic.CompareAndSwapPointer(p, unsafe.Pointer(&*c.node), unsafe.Pointer(&*next))
2021-05-22 17:10:26 +08:00
return nil
}