2021-05-21 23:07:48 +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-21 23:07:48 +08:00
|
|
|
"sync/atomic"
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
type ConcurrentLinkedQueue[T lang.Object] struct {
|
|
|
|
head *concurrentLinkedQueueNode[T]
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c ConcurrentLinkedQueue[T]) String() string {
|
|
|
|
return String[T](c)
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
type concurrentLinkedQueueNode[T any] struct {
|
|
|
|
value T
|
|
|
|
prev *concurrentLinkedQueueNode[T]
|
|
|
|
next *concurrentLinkedQueueNode[T]
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
type concurrentLinkedQueueIterator[T any] struct {
|
|
|
|
head *concurrentLinkedQueueNode[T]
|
|
|
|
node *concurrentLinkedQueueNode[T]
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func NewConcurrentLinkedQueue[T lang.Object]() *ConcurrentLinkedQueue[T] {
|
|
|
|
head := &concurrentLinkedQueueNode[T]{}
|
2021-05-22 17:10:26 +08:00
|
|
|
head.prev = head
|
|
|
|
head.next = head
|
2022-03-21 11:02:41 +08:00
|
|
|
return &ConcurrentLinkedQueue[T]{head}
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c ConcurrentLinkedQueue[T]) Iterator() Iterator[T] {
|
2021-05-21 23:07:48 +08:00
|
|
|
return c.MutableIterator()
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) Push(element T) exceptions.Exception {
|
|
|
|
newNode := &concurrentLinkedQueueNode[T]{element, c.head.prev, c.head}
|
2021-05-22 17:10:26 +08:00
|
|
|
p := (*unsafe.Pointer)(unsafe.Pointer(&c.head.prev))
|
2022-03-21 11:02:41 +08:00
|
|
|
for !atomic.CompareAndSwapPointer(p, unsafe.Pointer(&*newNode.prev), unsafe.Pointer(newNode)) {
|
2021-05-22 17:10:26 +08:00
|
|
|
newNode.prev = c.head.prev
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
2021-05-22 17:10:26 +08:00
|
|
|
atomic.CompareAndSwapPointer(
|
|
|
|
(*unsafe.Pointer)(unsafe.Pointer(&newNode.prev.next)),
|
2022-03-21 11:02:41 +08:00
|
|
|
unsafe.Pointer(&*c.head),
|
2021-05-22 17:10:26 +08:00
|
|
|
unsafe.Pointer(newNode),
|
|
|
|
)
|
2021-05-21 23:07:48 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) Offer() (T, exceptions.Exception) {
|
2021-05-21 23:07:48 +08:00
|
|
|
next := c.head.next
|
2021-05-22 17:10:26 +08:00
|
|
|
if next == c.head {
|
2022-03-21 11:02:41 +08:00
|
|
|
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2021-05-22 17:10:26 +08:00
|
|
|
p := (*unsafe.Pointer)(unsafe.Pointer(&next.next.prev))
|
2021-05-21 23:07:48 +08:00
|
|
|
|
2021-05-22 17:10:26 +08:00
|
|
|
if !next.removeNode(p) {
|
2021-05-21 23:07:48 +08:00
|
|
|
next = c.head.next
|
2021-05-22 17:10:26 +08:00
|
|
|
p = (*unsafe.Pointer)(unsafe.Pointer(&next.prev))
|
2021-05-21 23:07:48 +08:00
|
|
|
if next == nil {
|
2022-03-21 11:02:41 +08:00
|
|
|
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return next.value, nil
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (node *concurrentLinkedQueueNode[T]) removeNode(p *unsafe.Pointer) bool {
|
2021-05-22 17:10:26 +08:00
|
|
|
if p == nil {
|
|
|
|
p = (*unsafe.Pointer)(unsafe.Pointer(&node.next.prev))
|
|
|
|
}
|
2022-03-21 11:02:41 +08:00
|
|
|
if !atomic.CompareAndSwapPointer(p, unsafe.Pointer(node), unsafe.Pointer(&*node.prev)) {
|
2021-05-22 17:10:26 +08:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
atomic.CompareAndSwapPointer(
|
|
|
|
(*unsafe.Pointer)(unsafe.Pointer(&node.prev.next)),
|
|
|
|
unsafe.Pointer(node),
|
2022-03-21 11:02:41 +08:00
|
|
|
unsafe.Pointer(&*node.next),
|
2021-05-22 17:10:26 +08:00
|
|
|
)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) MutableIterator() MutableIterator[T] {
|
|
|
|
return &concurrentLinkedQueueIterator[T]{c.head, c.head}
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *concurrentLinkedQueueIterator[T]) HasNext() bool {
|
2021-05-22 17:10:26 +08:00
|
|
|
return c.node.next != c.head
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *concurrentLinkedQueueIterator[T]) Next() (T, exceptions.Exception) {
|
2021-05-22 17:10:26 +08:00
|
|
|
c.node = c.node.next
|
|
|
|
if c.node == c.head {
|
2022-03-21 11:02:41 +08:00
|
|
|
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
2021-05-22 17:10:26 +08:00
|
|
|
return c.node.value, nil
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *concurrentLinkedQueueIterator[T]) Remove() exceptions.Exception {
|
2021-05-22 17:10:26 +08:00
|
|
|
if c.node == c.head {
|
2022-03-21 11:02:41 +08:00
|
|
|
return exceptions.NewIndexOutOfBound("", nil)
|
2021-05-21 23:07:48 +08:00
|
|
|
}
|
2021-05-22 17:10:26 +08:00
|
|
|
c.node.removeNode(nil)
|
|
|
|
c.node = c.node.prev
|
2021-05-21 23:07:48 +08:00
|
|
|
return nil
|
|
|
|
}
|
2021-05-22 17:10:26 +08:00
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) Size() int {
|
|
|
|
size, err := Size[T](c)
|
2021-05-22 17:10:26 +08:00
|
|
|
exceptions.Print(err)
|
|
|
|
return size
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) IsEmpty() bool {
|
2021-05-22 17:10:26 +08:00
|
|
|
return c.head.next == c.head
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) Contains(element T) bool {
|
|
|
|
return Contains[T](c, element)
|
2021-05-22 17:10:26 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) ContainsAll(collection Collection[T]) bool {
|
|
|
|
return ContainsAll[T](c, collection)
|
2021-05-22 17:10:26 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) Add(element T) bool {
|
2021-05-22 17:10:26 +08:00
|
|
|
exception := c.Push(element)
|
|
|
|
exceptions.Print(exception)
|
|
|
|
return exception == nil
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) Remove(element T) exceptions.Exception {
|
|
|
|
return Remove[T](c, element)
|
2021-05-22 17:10:26 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) AddAll(collection Collection[T]) bool {
|
|
|
|
return AddAll[T](c, collection)
|
2021-05-22 17:10:26 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) RemoveAll(collection Collection[T]) bool {
|
|
|
|
return RemoveAll[T](c, collection)
|
2021-05-22 17:10:26 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) RetainAll(collection Collection[T]) bool {
|
|
|
|
return RetainAll[T](c, collection)
|
2021-05-22 17:10:26 +08:00
|
|
|
}
|
|
|
|
|
2022-03-21 11:02:41 +08:00
|
|
|
func (c *ConcurrentLinkedQueue[T]) Clear() {
|
|
|
|
head := &concurrentLinkedQueueNode[T]{}
|
2021-05-22 17:10:26 +08:00
|
|
|
head.prev = head
|
|
|
|
head.next = head
|
|
|
|
c.head = head
|
|
|
|
}
|