mirror of
https://github.com/tursom/GoCollections.git
synced 2026-08-22 15:13:29 +08:00
impl ConcurrentLinkedStack and ConcurrentLinkedQueue
This commit is contained in:
@@ -3,157 +3,166 @@ package collections
|
||||
import (
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
"github.com/tursom/GoCollections/lang"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
"github.com/tursom/GoCollections/lang/atomic"
|
||||
)
|
||||
|
||||
type ConcurrentLinkedQueue[T lang.Object] struct {
|
||||
lang.BaseObject
|
||||
head *concurrentLinkedQueueNode[T]
|
||||
}
|
||||
type (
|
||||
ConcurrentLinkedQueueNode[T lang.Object] interface {
|
||||
Get() (T, exceptions.Exception)
|
||||
Remove() exceptions.Exception
|
||||
RemoveAndGet() (T, exceptions.Exception)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) String() string {
|
||||
return String[T](c)
|
||||
}
|
||||
ConcurrentLinkedQueue[T lang.Object] struct {
|
||||
lang.BaseObject
|
||||
ConcurrentLinkedStack[T]
|
||||
end *concurrentLinkedStackNode[T]
|
||||
}
|
||||
|
||||
type concurrentLinkedQueueNode[T any] struct {
|
||||
value T
|
||||
prev *concurrentLinkedQueueNode[T]
|
||||
next *concurrentLinkedQueueNode[T]
|
||||
}
|
||||
concurrentLinkedQueueIterator[T lang.Object] struct {
|
||||
node *concurrentLinkedStackNode[T]
|
||||
queue *ConcurrentLinkedQueue[T]
|
||||
}
|
||||
)
|
||||
|
||||
type concurrentLinkedQueueIterator[T any] struct {
|
||||
head *concurrentLinkedQueueNode[T]
|
||||
node *concurrentLinkedQueueNode[T]
|
||||
func (q *ConcurrentLinkedQueue[T]) String() string {
|
||||
return String[T](q)
|
||||
}
|
||||
|
||||
func NewConcurrentLinkedQueue[T lang.Object]() *ConcurrentLinkedQueue[T] {
|
||||
head := &concurrentLinkedQueueNode[T]{}
|
||||
head.prev = head
|
||||
head.next = head
|
||||
return &ConcurrentLinkedQueue[T]{lang.NewBaseObject(), head}
|
||||
return &ConcurrentLinkedQueue[T]{}
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Iterator() Iterator[T] {
|
||||
return c.MutableIterator()
|
||||
func (q *ConcurrentLinkedQueue[T]) Iterator() Iterator[T] {
|
||||
return q.MutableIterator()
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Push(element T) exceptions.Exception {
|
||||
newNode := &concurrentLinkedQueueNode[T]{element, c.head.prev, c.head}
|
||||
p := (*unsafe.Pointer)(unsafe.Pointer(&c.head.prev))
|
||||
for !atomic.CompareAndSwapPointer(p, unsafe.Pointer(&*newNode.prev), unsafe.Pointer(newNode)) {
|
||||
newNode.prev = c.head.prev
|
||||
func (q *ConcurrentLinkedQueue[T]) Offer(element T) exceptions.Exception {
|
||||
_, err := q.offerAndGetNode(element)
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *ConcurrentLinkedQueue[T]) OfferAndGetNode(element T) (ConcurrentLinkedQueueNode[T], exceptions.Exception) {
|
||||
newNode, err := q.offerAndGetNode(element)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
atomic.CompareAndSwapPointer(
|
||||
(*unsafe.Pointer)(unsafe.Pointer(&newNode.prev.next)),
|
||||
unsafe.Pointer(&*c.head),
|
||||
unsafe.Pointer(newNode),
|
||||
)
|
||||
return nil
|
||||
return &concurrentLinkedQueueIterator[T]{queue: q, node: newNode}, nil
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Offer() (T, exceptions.Exception) {
|
||||
next := c.head.next
|
||||
if next == c.head {
|
||||
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
|
||||
func (q *ConcurrentLinkedQueue[T]) offerAndGetNode(element T) (*concurrentLinkedStackNode[T], exceptions.Exception) {
|
||||
newNode := &concurrentLinkedStackNode[T]{value: element}
|
||||
q.size.Add(1)
|
||||
|
||||
var next **concurrentLinkedStackNode[T]
|
||||
ref := q.end
|
||||
switch {
|
||||
case ref == nil:
|
||||
next = &q.head
|
||||
default:
|
||||
next = &ref.next
|
||||
}
|
||||
|
||||
p := (*unsafe.Pointer)(unsafe.Pointer(&next.next.prev))
|
||||
|
||||
if !next.removeNode(p) {
|
||||
next = c.head.next
|
||||
p = (*unsafe.Pointer)(unsafe.Pointer(&next.prev))
|
||||
if next == nil {
|
||||
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
|
||||
for !atomic.CompareAndSwapPointer(next, nil, newNode) {
|
||||
if ref == nil || ref.next == nil {
|
||||
next = &q.head
|
||||
ref = q.head
|
||||
} else {
|
||||
for ref.next != nil {
|
||||
ref = ref.next
|
||||
}
|
||||
next = &ref.next
|
||||
}
|
||||
}
|
||||
|
||||
return next.value, nil
|
||||
q.end = newNode
|
||||
return newNode, nil
|
||||
}
|
||||
|
||||
func (node *concurrentLinkedQueueNode[T]) removeNode(p *unsafe.Pointer) bool {
|
||||
if p == nil {
|
||||
p = (*unsafe.Pointer)(unsafe.Pointer(&node.next.prev))
|
||||
}
|
||||
if !atomic.CompareAndSwapPointer(p, unsafe.Pointer(node), unsafe.Pointer(&*node.prev)) {
|
||||
return false
|
||||
}
|
||||
atomic.CompareAndSwapPointer(
|
||||
(*unsafe.Pointer)(unsafe.Pointer(&node.prev.next)),
|
||||
unsafe.Pointer(node),
|
||||
unsafe.Pointer(&*node.next),
|
||||
)
|
||||
return true
|
||||
func (q *ConcurrentLinkedQueue[T]) Poll() (T, exceptions.Exception) {
|
||||
return q.Pop()
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) MutableIterator() MutableIterator[T] {
|
||||
return &concurrentLinkedQueueIterator[T]{c.head, c.head}
|
||||
func (q *ConcurrentLinkedQueue[T]) MutableIterator() MutableIterator[T] {
|
||||
return &concurrentLinkedQueueIterator[T]{node: q.head}
|
||||
}
|
||||
|
||||
func (c *concurrentLinkedQueueIterator[T]) HasNext() bool {
|
||||
return c.node.next != c.head
|
||||
func (q *ConcurrentLinkedQueue[T]) Size() int {
|
||||
return int(q.size.Load())
|
||||
}
|
||||
|
||||
func (c *concurrentLinkedQueueIterator[T]) Next() (T, exceptions.Exception) {
|
||||
c.node = c.node.next
|
||||
if c.node == c.head {
|
||||
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
|
||||
}
|
||||
return c.node.value, nil
|
||||
func (q *ConcurrentLinkedQueue[T]) IsEmpty() bool {
|
||||
return q.head == nil
|
||||
}
|
||||
|
||||
func (c *concurrentLinkedQueueIterator[T]) Remove() exceptions.Exception {
|
||||
if c.node == c.head {
|
||||
return exceptions.NewIndexOutOfBound("", nil)
|
||||
}
|
||||
c.node.removeNode(nil)
|
||||
c.node = c.node.prev
|
||||
return nil
|
||||
func (q *ConcurrentLinkedQueue[T]) Contains(element T) bool {
|
||||
return Contains[T](q, element)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Size() int {
|
||||
size, err := Size[T](c)
|
||||
exceptions.Print(err)
|
||||
return size
|
||||
func (q *ConcurrentLinkedQueue[T]) ContainsAll(collection Collection[T]) bool {
|
||||
return ContainsAll[T](q, collection)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) IsEmpty() bool {
|
||||
return c.head.next == c.head
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Contains(element T) bool {
|
||||
return Contains[T](c, element)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) ContainsAll(collection Collection[T]) bool {
|
||||
return ContainsAll[T](c, collection)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Add(element T) bool {
|
||||
exception := c.Push(element)
|
||||
func (q *ConcurrentLinkedQueue[T]) Add(element T) bool {
|
||||
exception := q.Push(element)
|
||||
exceptions.Print(exception)
|
||||
return exception == nil
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Remove(element T) exceptions.Exception {
|
||||
return Remove[T](c, element)
|
||||
func (q *ConcurrentLinkedQueue[T]) Remove(element T) exceptions.Exception {
|
||||
return Remove[T](q, element)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) AddAll(collection Collection[T]) bool {
|
||||
return AddAll[T](c, collection)
|
||||
func (q *ConcurrentLinkedQueue[T]) AddAll(collection Collection[T]) bool {
|
||||
return AddAll[T](q, collection)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) RemoveAll(collection Collection[T]) bool {
|
||||
return RemoveAll[T](c, collection)
|
||||
func (q *ConcurrentLinkedQueue[T]) RemoveAll(collection Collection[T]) bool {
|
||||
return RemoveAll[T](q, collection)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) RetainAll(collection Collection[T]) bool {
|
||||
return RetainAll[T](c, collection)
|
||||
func (q *ConcurrentLinkedQueue[T]) RetainAll(collection Collection[T]) bool {
|
||||
return RetainAll[T](q, collection)
|
||||
}
|
||||
|
||||
func (c *ConcurrentLinkedQueue[T]) Clear() {
|
||||
head := &concurrentLinkedQueueNode[T]{}
|
||||
head.prev = head
|
||||
head.next = head
|
||||
c.head = head
|
||||
func (q *ConcurrentLinkedQueue[T]) Clear() {
|
||||
q.head = nil
|
||||
q.end = nil
|
||||
q.size.Store(0)
|
||||
}
|
||||
|
||||
func (i *concurrentLinkedQueueIterator[T]) HasNext() bool {
|
||||
for i.node != nil && i.node.deleted {
|
||||
i.node = i.node.next
|
||||
}
|
||||
return i.node != nil
|
||||
}
|
||||
|
||||
func (i *concurrentLinkedQueueIterator[T]) Next() (T, exceptions.Exception) {
|
||||
value, err := i.Get()
|
||||
i.node = i.node.next
|
||||
for i.node != nil && i.node.deleted {
|
||||
i.node = i.node.next
|
||||
}
|
||||
return value, err
|
||||
}
|
||||
|
||||
func (i *concurrentLinkedQueueIterator[T]) Get() (T, exceptions.Exception) {
|
||||
return (*i.node).value, nil
|
||||
}
|
||||
|
||||
func (i *concurrentLinkedQueueIterator[T]) Remove() exceptions.Exception {
|
||||
_, err := i.RemoveAndGet()
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *concurrentLinkedQueueIterator[T]) RemoveAndGet() (T, exceptions.Exception) {
|
||||
if i.node == nil {
|
||||
return lang.Nil[T](), nil
|
||||
}
|
||||
load := i.node
|
||||
load.deleted = true
|
||||
i.queue.size.Add(-1)
|
||||
i.queue.deleted.Add(1)
|
||||
i.queue.CleanDeleted()
|
||||
i.node = load.next
|
||||
return load.value, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user