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
|
|
|
|
}
|