From c7576d9b3b43cc201ee9ad7a8d759a5a0cf6a180 Mon Sep 17 00:00:00 2001
From: tursom <tursom@foxmail.com>
Date: Fri, 21 May 2021 23:07:48 +0800
Subject: [PATCH] add ConcurrentLinkedQueue

---
 collections/Collection.go            |  6 +-
 collections/ConcurrentLinkedQueue.go | 92 ++++++++++++++++++++++++++++
 collections/Queue.go                 | 13 ++++
 main.go                              |  6 +-
 4 files changed, 111 insertions(+), 6 deletions(-)
 create mode 100644 collections/ConcurrentLinkedQueue.go
 create mode 100644 collections/Queue.go

diff --git a/collections/Collection.go b/collections/Collection.go
index e0f97dc..6dc0b30 100644
--- a/collections/Collection.go
+++ b/collections/Collection.go
@@ -110,14 +110,14 @@ func RetainAll(l MutableCollection, collection Collection) bool {
 	}) == nil
 }
 
-func String(l List) string {
-	if l.IsEmpty() {
+func String(l Iterable) string {
+	iterator := l.Iterator()
+	if !iterator.HasNext() {
 		return "[]"
 	}
 
 	builder := strings.Builder{}
 	builder.WriteString("[")
-	iterator := l.Iterator()
 	next, _ := iterator.Next()
 	builder.WriteString(fmt.Sprint(next))
 	for iterator.HasNext() {
diff --git a/collections/ConcurrentLinkedQueue.go b/collections/ConcurrentLinkedQueue.go
new file mode 100644
index 0000000..96ff2e4
--- /dev/null
+++ b/collections/ConcurrentLinkedQueue.go
@@ -0,0 +1,92 @@
+package collections
+
+import (
+	"github.com/tursom/GoCollections/exceptions"
+	"sync/atomic"
+	"unsafe"
+)
+
+type ConcurrentLinkedQueue struct {
+	head *concurrentLinkedQueueNode
+	tail *concurrentLinkedQueueNode
+}
+
+func (c ConcurrentLinkedQueue) String() string {
+	return String(c)
+}
+
+type concurrentLinkedQueueNode struct {
+	value interface{}
+	next  *concurrentLinkedQueueNode
+}
+
+type concurrentLinkedQueueIterator struct {
+	prev *concurrentLinkedQueueNode
+	head *concurrentLinkedQueueNode
+}
+
+func NewConcurrentLinkedQueue() *ConcurrentLinkedQueue {
+	head := &concurrentLinkedQueueNode{}
+	return &ConcurrentLinkedQueue{head, head}
+}
+
+func (c ConcurrentLinkedQueue) Iterator() Iterator {
+	return c.MutableIterator()
+}
+
+func (c *ConcurrentLinkedQueue) Push(element interface{}) exceptions.Exception {
+	newNode := &concurrentLinkedQueueNode{element, nil}
+	p := (*unsafe.Pointer)(unsafe.Pointer(&c.tail.next))
+	np := unsafe.Pointer(newNode)
+	for !atomic.CompareAndSwapPointer(p, nil, np) {
+		p = (*unsafe.Pointer)(unsafe.Pointer(&c.tail.next))
+	}
+	c.tail = newNode
+	return nil
+}
+
+func (c *ConcurrentLinkedQueue) Offer() (interface{}, exceptions.Exception) {
+	next := c.head.next
+	if next == nil {
+		return nil, exceptions.NewIndexOutOfBound("", true)
+	}
+
+	p := (*unsafe.Pointer)(unsafe.Pointer(&c.head.next))
+
+	if !atomic.CompareAndSwapPointer(p, unsafe.Pointer(next), unsafe.Pointer(next.next)) {
+		next = c.head.next
+		if next == nil {
+			return nil, exceptions.NewIndexOutOfBound("", true)
+		}
+	}
+
+	return next.value, nil
+}
+
+func (c *ConcurrentLinkedQueue) MutableIterator() MutableIterator {
+	return &concurrentLinkedQueueIterator{nil, c.head}
+}
+
+func (c *concurrentLinkedQueueIterator) HasNext() bool {
+	return c.head.next != nil
+}
+
+func (c *concurrentLinkedQueueIterator) Next() (interface{}, exceptions.Exception) {
+	c.prev = c.head
+	c.head = c.head.next
+	if c.head == nil {
+		return nil, exceptions.NewIndexOutOfBound("", true)
+	}
+	return c.head.value, nil
+}
+
+func (c *concurrentLinkedQueueIterator) Remove() exceptions.Exception {
+	next := c.head.next
+	if next == nil {
+		return exceptions.NewIndexOutOfBound("", true)
+	}
+
+	p := (*unsafe.Pointer)(unsafe.Pointer(&c.prev.next))
+	atomic.CompareAndSwapPointer(p, unsafe.Pointer(c.head), unsafe.Pointer(next))
+	return nil
+}
diff --git a/collections/Queue.go b/collections/Queue.go
new file mode 100644
index 0000000..0d34393
--- /dev/null
+++ b/collections/Queue.go
@@ -0,0 +1,13 @@
+package collections
+
+import "github.com/tursom/GoCollections/exceptions"
+
+type Queue interface {
+	// Iterator MutableIterable
+	Iterator() Iterator
+	// MutableIterator MutableIterable
+	MutableIterator() MutableIterator
+
+	Push(element interface{}) exceptions.Exception
+	Offer() (interface{}, exceptions.Exception)
+}
diff --git a/main.go b/main.go
index aaa3b6e..d56c2e8 100644
--- a/main.go
+++ b/main.go
@@ -15,11 +15,11 @@ func main() {
 	})
 	exceptions.Print(err)
 
-	list := collections.NewArrayList()
+	list := collections.NewConcurrentLinkedQueue()
 	fmt.Println(list)
 	for i := 0; i < 20; i++ {
-		list.Add(i)
-		//fmt.Println(list)
+		list.Push(i)
+		fmt.Println(list)
 	}
 
 	_ = collections.LoopMutable(list, func(element interface{}, iterator collections.MutableIterator) (err exceptions.Exception) {