diff --git a/collections/ArrayList.go b/collections/ArrayList.go index f3b5273..fae8fe5 100644 --- a/collections/ArrayList.go +++ b/collections/ArrayList.go @@ -14,6 +14,13 @@ func NewArrayList() *ArrayList { } } +func NewArrayListByCapacity(cap uint32) *ArrayList { + return &ArrayList{ + make([]interface{}, cap), + 0, + } +} + func (a ArrayList) String() string { return String(a) } diff --git a/collections/Collection.go b/collections/Collection.go index 6dc0b30..815a19d 100644 --- a/collections/Collection.go +++ b/collections/Collection.go @@ -67,15 +67,6 @@ type ( } ) -func Contains(l Collection, element interface{}) bool { - return Loop(l, func(e interface{}) exceptions.Exception { - if e == element { - return exceptions.ElementFound - } - return nil - }) != nil -} - func ContainsAll(l Collection, collection Collection) bool { return Loop(collection, func(e interface{}) exceptions.Exception { if l.Contains(e) { @@ -95,21 +86,6 @@ func AddAll(l MutableCollection, collection Collection) bool { }) == nil } -func RemoveAll(l MutableCollection, collection Collection) bool { - return Loop(collection, func(e interface{}) exceptions.Exception { - return l.Remove(e) - }) == nil -} - -func RetainAll(l MutableCollection, collection Collection) bool { - return LoopMutable(l, func(element interface{}, iterator MutableIterator) exceptions.Exception { - if !collection.Contains(element) { - return iterator.Remove() - } - return nil - }) == nil -} - func String(l Iterable) string { iterator := l.Iterator() if !iterator.HasNext() { diff --git a/collections/ConcurrentLinkedQueue.go b/collections/ConcurrentLinkedQueue.go index 96ff2e4..a27f46f 100644 --- a/collections/ConcurrentLinkedQueue.go +++ b/collections/ConcurrentLinkedQueue.go @@ -8,7 +8,6 @@ import ( type ConcurrentLinkedQueue struct { head *concurrentLinkedQueueNode - tail *concurrentLinkedQueueNode } func (c ConcurrentLinkedQueue) String() string { @@ -17,17 +16,20 @@ func (c ConcurrentLinkedQueue) String() string { type concurrentLinkedQueueNode struct { value interface{} + prev *concurrentLinkedQueueNode next *concurrentLinkedQueueNode } type concurrentLinkedQueueIterator struct { - prev *concurrentLinkedQueueNode head *concurrentLinkedQueueNode + node *concurrentLinkedQueueNode } func NewConcurrentLinkedQueue() *ConcurrentLinkedQueue { head := &concurrentLinkedQueueNode{} - return &ConcurrentLinkedQueue{head, head} + head.prev = head + head.next = head + return &ConcurrentLinkedQueue{head} } func (c ConcurrentLinkedQueue) Iterator() Iterator { @@ -35,26 +37,30 @@ func (c ConcurrentLinkedQueue) Iterator() Iterator { } 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)) + newNode := &concurrentLinkedQueueNode{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 } - c.tail = newNode + atomic.CompareAndSwapPointer( + (*unsafe.Pointer)(unsafe.Pointer(&newNode.prev.next)), + unsafe.Pointer(c.head), + unsafe.Pointer(newNode), + ) return nil } func (c *ConcurrentLinkedQueue) Offer() (interface{}, exceptions.Exception) { next := c.head.next - if next == nil { + if next == c.head { return nil, exceptions.NewIndexOutOfBound("", true) } - p := (*unsafe.Pointer)(unsafe.Pointer(&c.head.next)) + p := (*unsafe.Pointer)(unsafe.Pointer(&next.next.prev)) - if !atomic.CompareAndSwapPointer(p, unsafe.Pointer(next), unsafe.Pointer(next.next)) { + if !next.removeNode(p) { next = c.head.next + p = (*unsafe.Pointer)(unsafe.Pointer(&next.prev)) if next == nil { return nil, exceptions.NewIndexOutOfBound("", true) } @@ -63,30 +69,89 @@ func (c *ConcurrentLinkedQueue) Offer() (interface{}, exceptions.Exception) { return next.value, nil } +func (node *concurrentLinkedQueueNode) 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 (c *ConcurrentLinkedQueue) MutableIterator() MutableIterator { - return &concurrentLinkedQueueIterator{nil, c.head} + return &concurrentLinkedQueueIterator{c.head, c.head} } func (c *concurrentLinkedQueueIterator) HasNext() bool { - return c.head.next != nil + return c.node.next != c.head } func (c *concurrentLinkedQueueIterator) Next() (interface{}, exceptions.Exception) { - c.prev = c.head - c.head = c.head.next - if c.head == nil { + c.node = c.node.next + if c.node == c.head { return nil, exceptions.NewIndexOutOfBound("", true) } - return c.head.value, nil + return c.node.value, nil } func (c *concurrentLinkedQueueIterator) Remove() exceptions.Exception { - next := c.head.next - if next == nil { + if c.node == c.head { return exceptions.NewIndexOutOfBound("", true) } - - p := (*unsafe.Pointer)(unsafe.Pointer(&c.prev.next)) - atomic.CompareAndSwapPointer(p, unsafe.Pointer(c.head), unsafe.Pointer(next)) + c.node.removeNode(nil) + c.node = c.node.prev return nil } + +func (c *ConcurrentLinkedQueue) Size() uint32 { + size, err := Size(c) + exceptions.Print(err) + return size +} + +func (c *ConcurrentLinkedQueue) IsEmpty() bool { + return c.head.next == c.head +} + +func (c *ConcurrentLinkedQueue) Contains(element interface{}) bool { + return Contains(c, element) +} + +func (c *ConcurrentLinkedQueue) ContainsAll(collection Collection) bool { + return ContainsAll(c, collection) +} + +func (c *ConcurrentLinkedQueue) Add(element interface{}) bool { + exception := c.Push(element) + exceptions.Print(exception) + return exception == nil +} + +func (c *ConcurrentLinkedQueue) Remove(element interface{}) exceptions.Exception { + return Remove(c, element) +} + +func (c *ConcurrentLinkedQueue) AddAll(collection Collection) bool { + return AddAll(c, collection) +} + +func (c *ConcurrentLinkedQueue) RemoveAll(collection Collection) bool { + return RemoveAll(c, collection) +} + +func (c *ConcurrentLinkedQueue) RetainAll(collection Collection) bool { + return RetainAll(c, collection) +} + +func (c *ConcurrentLinkedQueue) Clear() { + head := &concurrentLinkedQueueNode{} + head.prev = head + head.next = head + c.head = head +} diff --git a/collections/ConcurrentLinkedStack.go b/collections/ConcurrentLinkedStack.go new file mode 100644 index 0000000..a9dad15 --- /dev/null +++ b/collections/ConcurrentLinkedStack.go @@ -0,0 +1,89 @@ +package collections + +import ( + "github.com/tursom/GoCollections/exceptions" + "sync/atomic" + "unsafe" +) + +type ConcurrentLinkedStack struct { + head *concurrentLinkedStackNode + p *unsafe.Pointer +} + +func (c ConcurrentLinkedStack) String() string { + return String(c) +} + +type concurrentLinkedStackNode struct { + value interface{} + next *concurrentLinkedStackNode +} + +type concurrentLinkedStackIterator struct { + node *concurrentLinkedStackNode + prev *concurrentLinkedStackNode +} + +func NewConcurrentLinkedStack() *ConcurrentLinkedStack { + head := &concurrentLinkedStackNode{} + return &ConcurrentLinkedStack{head, (*unsafe.Pointer)(unsafe.Pointer(&head.next))} +} + +func (c ConcurrentLinkedStack) Iterator() Iterator { + return c.MutableIterator() +} + +func (c *ConcurrentLinkedStack) Push(element interface{}) exceptions.Exception { + newNode := &concurrentLinkedStackNode{element, c.head.next} + np := unsafe.Pointer(newNode) + for !atomic.CompareAndSwapPointer(c.p, unsafe.Pointer(newNode.next), np) { + } + return nil +} + +func (c *ConcurrentLinkedStack) Pop() (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 *ConcurrentLinkedStack) MutableIterator() MutableIterator { + return &concurrentLinkedStackIterator{c.head, nil} +} + +func (c *concurrentLinkedStackIterator) HasNext() bool { + return c.node.next != nil +} + +func (c *concurrentLinkedStackIterator) Next() (interface{}, exceptions.Exception) { + c.prev = c.node + c.node = c.node.next + if c.node == nil { + return nil, exceptions.NewIndexOutOfBound("", true) + } + return c.node.value, nil +} + +func (c *concurrentLinkedStackIterator) Remove() exceptions.Exception { + if c.node == nil { + return exceptions.NewIndexOutOfBound("", true) + } + next := c.node.next + + p := (*unsafe.Pointer)(unsafe.Pointer(&c.prev.next)) + atomic.CompareAndSwapPointer(p, unsafe.Pointer(c.node), unsafe.Pointer(next)) + return nil +} diff --git a/collections/Iterable.go b/collections/Iterable.go index 383b31e..f16fe7f 100644 --- a/collections/Iterable.go +++ b/collections/Iterable.go @@ -69,3 +69,57 @@ func LoopMutableIterator(iterator MutableIterator, f func(element interface{}, i } return nil } + +func Size(iterable Iterable) (size uint32, err exceptions.Exception) { + iterator := iterable.Iterator() + for iterator.HasNext() { + _, err = iterator.Next() + if err != nil { + return + } + size++ + } + return +} + +func Contains(l Iterable, element interface{}) bool { + return Loop(l, func(e interface{}) exceptions.Exception { + if e == element { + return exceptions.ElementFound + } + return nil + }) != nil +} + +func Remove(l MutableIterable, element interface{}) exceptions.Exception { + return LoopMutable(l, func(e interface{}, iterator MutableIterator) (err exceptions.Exception) { + if element == e { + return iterator.Remove() + } + return nil + }) +} + +func RemoveAll(l MutableIterable, collection Collection) bool { + return LoopMutable(l, func(element interface{}, iterator MutableIterator) (err exceptions.Exception) { + if collection.Contains(element) { + return iterator.Remove() + } + return nil + }) == nil +} + +func RetainAll(l MutableIterable, collection Collection) bool { + return LoopMutable(l, func(element interface{}, iterator MutableIterator) exceptions.Exception { + if !collection.Contains(element) { + return iterator.Remove() + } + return nil + }) == nil +} + +func Clear(l MutableIterable) exceptions.Exception { + return LoopMutable(l, func(element interface{}, iterator MutableIterator) (err exceptions.Exception) { + return iterator.Remove() + }) +} diff --git a/collections/Stack.go b/collections/Stack.go new file mode 100644 index 0000000..96625e6 --- /dev/null +++ b/collections/Stack.go @@ -0,0 +1,13 @@ +package collections + +import "github.com/tursom/GoCollections/exceptions" + +type Stack interface { + // Iterator MutableIterable + Iterator() Iterator + // MutableIterator MutableIterable + MutableIterator() MutableIterator + + Push(element interface{}) exceptions.Exception + Pop() (interface{}, exceptions.Exception) +} diff --git a/main.go b/main.go index d56c2e8..aaf18e2 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/tursom/GoCollections/collections" "github.com/tursom/GoCollections/exceptions" + "time" ) func main() { @@ -16,19 +17,57 @@ func main() { exceptions.Print(err) list := collections.NewConcurrentLinkedQueue() - fmt.Println(list) - for i := 0; i < 20; i++ { - list.Push(i) - fmt.Println(list) - } + target := collections.NewArrayListByCapacity(10000) + fmt.Println("list", list) - _ = collections.LoopMutable(list, func(element interface{}, iterator collections.MutableIterator) (err exceptions.Exception) { - if element.(int)&1 == 0 { - err = iterator.Remove() + go func() { + for i := 0; i < 1000000; i++ { + element, _ := list.Offer() + //fmt.Println(offer) + if element != nil { + target.Add(element) + } } + fmt.Println("target:", target) + }() + + go func() { + for i := 0; i < 1000; i++ { + err = list.Push(i) + //fmt.Println(err) + } + time.Sleep(time.Second * 2) fmt.Println(list) - return - }) + }() + // + //for i := 0; i < 100; i++ { + // fmt.Println(list) + //} + time.Sleep(time.Second * 10) + fmt.Println("target:", target) + + //for i := 0; i < 20; i++ { + // list.Push(i) + // fmt.Println(list) + //} + // + //for i := 0; i < 20; i++ { + // list.Offer() + // fmt.Println(list) + //} + // + //for i := 0; i < 25; i++ { + // list.Push(i) + // fmt.Println(list) + //} + // + //_ = collections.LoopMutable(list, func(element interface{}, iterator collections.MutableIterator) (err exceptions.Exception) { + // if element.(int)&1 == 0 { + // err = iterator.Remove() + // } + // fmt.Println(list) + // return + //}) //for i := 0; i < 10; i++ { // list.Remove(i * 2) // fmt.Println(list)