mirror of
https://github.com/tursom/GoCollections.git
synced 2025-04-02 19:00:12 +08:00
update concurrent collections
This commit is contained in:
parent
c7576d9b3b
commit
055889a402
@ -14,6 +14,13 @@ func NewArrayList() *ArrayList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewArrayListByCapacity(cap uint32) *ArrayList {
|
||||||
|
return &ArrayList{
|
||||||
|
make([]interface{}, cap),
|
||||||
|
0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a ArrayList) String() string {
|
func (a ArrayList) String() string {
|
||||||
return String(a)
|
return String(a)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
func ContainsAll(l Collection, collection Collection) bool {
|
||||||
return Loop(collection, func(e interface{}) exceptions.Exception {
|
return Loop(collection, func(e interface{}) exceptions.Exception {
|
||||||
if l.Contains(e) {
|
if l.Contains(e) {
|
||||||
@ -95,21 +86,6 @@ func AddAll(l MutableCollection, collection Collection) bool {
|
|||||||
}) == nil
|
}) == 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 {
|
func String(l Iterable) string {
|
||||||
iterator := l.Iterator()
|
iterator := l.Iterator()
|
||||||
if !iterator.HasNext() {
|
if !iterator.HasNext() {
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
type ConcurrentLinkedQueue struct {
|
type ConcurrentLinkedQueue struct {
|
||||||
head *concurrentLinkedQueueNode
|
head *concurrentLinkedQueueNode
|
||||||
tail *concurrentLinkedQueueNode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConcurrentLinkedQueue) String() string {
|
func (c ConcurrentLinkedQueue) String() string {
|
||||||
@ -17,17 +16,20 @@ func (c ConcurrentLinkedQueue) String() string {
|
|||||||
|
|
||||||
type concurrentLinkedQueueNode struct {
|
type concurrentLinkedQueueNode struct {
|
||||||
value interface{}
|
value interface{}
|
||||||
|
prev *concurrentLinkedQueueNode
|
||||||
next *concurrentLinkedQueueNode
|
next *concurrentLinkedQueueNode
|
||||||
}
|
}
|
||||||
|
|
||||||
type concurrentLinkedQueueIterator struct {
|
type concurrentLinkedQueueIterator struct {
|
||||||
prev *concurrentLinkedQueueNode
|
|
||||||
head *concurrentLinkedQueueNode
|
head *concurrentLinkedQueueNode
|
||||||
|
node *concurrentLinkedQueueNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConcurrentLinkedQueue() *ConcurrentLinkedQueue {
|
func NewConcurrentLinkedQueue() *ConcurrentLinkedQueue {
|
||||||
head := &concurrentLinkedQueueNode{}
|
head := &concurrentLinkedQueueNode{}
|
||||||
return &ConcurrentLinkedQueue{head, head}
|
head.prev = head
|
||||||
|
head.next = head
|
||||||
|
return &ConcurrentLinkedQueue{head}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ConcurrentLinkedQueue) Iterator() Iterator {
|
func (c ConcurrentLinkedQueue) Iterator() Iterator {
|
||||||
@ -35,26 +37,30 @@ func (c ConcurrentLinkedQueue) Iterator() Iterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConcurrentLinkedQueue) Push(element interface{}) exceptions.Exception {
|
func (c *ConcurrentLinkedQueue) Push(element interface{}) exceptions.Exception {
|
||||||
newNode := &concurrentLinkedQueueNode{element, nil}
|
newNode := &concurrentLinkedQueueNode{element, c.head.prev, c.head}
|
||||||
p := (*unsafe.Pointer)(unsafe.Pointer(&c.tail.next))
|
p := (*unsafe.Pointer)(unsafe.Pointer(&c.head.prev))
|
||||||
np := unsafe.Pointer(newNode)
|
for !atomic.CompareAndSwapPointer(p, unsafe.Pointer(newNode.prev), unsafe.Pointer(newNode)) {
|
||||||
for !atomic.CompareAndSwapPointer(p, nil, np) {
|
newNode.prev = c.head.prev
|
||||||
p = (*unsafe.Pointer)(unsafe.Pointer(&c.tail.next))
|
|
||||||
}
|
}
|
||||||
c.tail = newNode
|
atomic.CompareAndSwapPointer(
|
||||||
|
(*unsafe.Pointer)(unsafe.Pointer(&newNode.prev.next)),
|
||||||
|
unsafe.Pointer(c.head),
|
||||||
|
unsafe.Pointer(newNode),
|
||||||
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConcurrentLinkedQueue) Offer() (interface{}, exceptions.Exception) {
|
func (c *ConcurrentLinkedQueue) Offer() (interface{}, exceptions.Exception) {
|
||||||
next := c.head.next
|
next := c.head.next
|
||||||
if next == nil {
|
if next == c.head {
|
||||||
return nil, exceptions.NewIndexOutOfBound("", true)
|
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
|
next = c.head.next
|
||||||
|
p = (*unsafe.Pointer)(unsafe.Pointer(&next.prev))
|
||||||
if next == nil {
|
if next == nil {
|
||||||
return nil, exceptions.NewIndexOutOfBound("", true)
|
return nil, exceptions.NewIndexOutOfBound("", true)
|
||||||
}
|
}
|
||||||
@ -63,30 +69,89 @@ func (c *ConcurrentLinkedQueue) Offer() (interface{}, exceptions.Exception) {
|
|||||||
return next.value, nil
|
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 {
|
func (c *ConcurrentLinkedQueue) MutableIterator() MutableIterator {
|
||||||
return &concurrentLinkedQueueIterator{nil, c.head}
|
return &concurrentLinkedQueueIterator{c.head, c.head}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *concurrentLinkedQueueIterator) HasNext() bool {
|
func (c *concurrentLinkedQueueIterator) HasNext() bool {
|
||||||
return c.head.next != nil
|
return c.node.next != c.head
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *concurrentLinkedQueueIterator) Next() (interface{}, exceptions.Exception) {
|
func (c *concurrentLinkedQueueIterator) Next() (interface{}, exceptions.Exception) {
|
||||||
c.prev = c.head
|
c.node = c.node.next
|
||||||
c.head = c.head.next
|
if c.node == c.head {
|
||||||
if c.head == nil {
|
|
||||||
return nil, exceptions.NewIndexOutOfBound("", true)
|
return nil, exceptions.NewIndexOutOfBound("", true)
|
||||||
}
|
}
|
||||||
return c.head.value, nil
|
return c.node.value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *concurrentLinkedQueueIterator) Remove() exceptions.Exception {
|
func (c *concurrentLinkedQueueIterator) Remove() exceptions.Exception {
|
||||||
next := c.head.next
|
if c.node == c.head {
|
||||||
if next == nil {
|
|
||||||
return exceptions.NewIndexOutOfBound("", true)
|
return exceptions.NewIndexOutOfBound("", true)
|
||||||
}
|
}
|
||||||
|
c.node.removeNode(nil)
|
||||||
p := (*unsafe.Pointer)(unsafe.Pointer(&c.prev.next))
|
c.node = c.node.prev
|
||||||
atomic.CompareAndSwapPointer(p, unsafe.Pointer(c.head), unsafe.Pointer(next))
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
89
collections/ConcurrentLinkedStack.go
Normal file
89
collections/ConcurrentLinkedStack.go
Normal file
@ -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
|
||||||
|
}
|
@ -69,3 +69,57 @@ func LoopMutableIterator(iterator MutableIterator, f func(element interface{}, i
|
|||||||
}
|
}
|
||||||
return nil
|
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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
13
collections/Stack.go
Normal file
13
collections/Stack.go
Normal file
@ -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)
|
||||||
|
}
|
59
main.go
59
main.go
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/tursom/GoCollections/collections"
|
"github.com/tursom/GoCollections/collections"
|
||||||
"github.com/tursom/GoCollections/exceptions"
|
"github.com/tursom/GoCollections/exceptions"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -16,19 +17,57 @@ func main() {
|
|||||||
exceptions.Print(err)
|
exceptions.Print(err)
|
||||||
|
|
||||||
list := collections.NewConcurrentLinkedQueue()
|
list := collections.NewConcurrentLinkedQueue()
|
||||||
fmt.Println(list)
|
target := collections.NewArrayListByCapacity(10000)
|
||||||
for i := 0; i < 20; i++ {
|
fmt.Println("list", list)
|
||||||
list.Push(i)
|
|
||||||
fmt.Println(list)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = collections.LoopMutable(list, func(element interface{}, iterator collections.MutableIterator) (err exceptions.Exception) {
|
go func() {
|
||||||
if element.(int)&1 == 0 {
|
for i := 0; i < 1000000; i++ {
|
||||||
err = iterator.Remove()
|
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)
|
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++ {
|
//for i := 0; i < 10; i++ {
|
||||||
// list.Remove(i * 2)
|
// list.Remove(i * 2)
|
||||||
// fmt.Println(list)
|
// fmt.Println(list)
|
||||||
|
Loading…
Reference in New Issue
Block a user