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) {