impl ConcurrentLinkedStack and ConcurrentLinkedQueue

This commit is contained in:
tursom 2022-03-30 20:49:59 +08:00
parent 150fa1f04e
commit 561ff20adb
19 changed files with 702 additions and 222 deletions

View File

@ -5,10 +5,16 @@ import (
"github.com/tursom/GoCollections/lang"
)
type ArrayList[T lang.Object] struct {
lang.BaseObject
array []T
}
type (
ArrayList[T lang.Object] struct {
lang.BaseObject
array []T
}
arrayListIterator[T lang.Object] struct {
arrayList *ArrayList[T]
index int
}
)
func NewArrayList[T lang.Object]() *ArrayList[T] {
return NewArrayListByCapacity[T](16)
@ -137,11 +143,6 @@ func (a *ArrayList[T]) RemoveLast() (T, exceptions.Exception) {
return v, a.RemoveAt(a.Size() - 1)
}
type arrayListIterator[T lang.Object] struct {
arrayList *ArrayList[T]
index int
}
func (a *arrayListIterator[T]) HasNext() bool {
return a.index < a.arrayList.Size()
}

View File

@ -9,7 +9,7 @@ import (
type (
Collection[T any] interface {
Iterator() Iterator[T]
Iterable[T]
Size() int
IsEmpty() bool
Contains(element T) bool
@ -17,13 +17,9 @@ type (
}
MutableCollection[T any] interface {
Iterator() Iterator[T]
Size() int
IsEmpty() bool
Contains(element T) bool
ContainsAll(c Collection[T]) bool
Collection[T]
MutableIterable[T]
MutableIterator() MutableIterator[T]
Add(element T) bool
Remove(element T) exceptions.Exception
AddAll(c Collection[T]) bool
@ -33,33 +29,15 @@ type (
}
List[T any] interface {
Iterator() Iterator[T]
Size() int
IsEmpty() bool
Contains(element T) bool
ContainsAll(c Collection[T]) bool
Collection[T]
Get(index int) (T, exceptions.Exception)
SubList(from, to int) List[T]
}
MutableList[T any] interface {
Iterator() Iterator[T]
Size() int
IsEmpty() bool
Contains(element T) bool
ContainsAll(c Collection[T]) bool
MutableIterator() MutableIterator[T]
Add(element T) bool
Remove(element T) exceptions.Exception
AddAll(c Collection[T]) bool
RemoveAll(c Collection[T]) bool
RetainAll(c Collection[T]) bool
Clear()
Get(index int) (T, exceptions.Exception)
SubList(from, to int) List[T]
List[T]
MutableCollection[T]
Set(index int, element T) exceptions.Exception
AddAtIndex(index int, element T) bool

View File

@ -3,157 +3,166 @@ package collections
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"sync/atomic"
"unsafe"
"github.com/tursom/GoCollections/lang/atomic"
)
type ConcurrentLinkedQueue[T lang.Object] struct {
lang.BaseObject
head *concurrentLinkedQueueNode[T]
}
type (
ConcurrentLinkedQueueNode[T lang.Object] interface {
Get() (T, exceptions.Exception)
Remove() exceptions.Exception
RemoveAndGet() (T, exceptions.Exception)
}
func (c *ConcurrentLinkedQueue[T]) String() string {
return String[T](c)
}
ConcurrentLinkedQueue[T lang.Object] struct {
lang.BaseObject
ConcurrentLinkedStack[T]
end *concurrentLinkedStackNode[T]
}
type concurrentLinkedQueueNode[T any] struct {
value T
prev *concurrentLinkedQueueNode[T]
next *concurrentLinkedQueueNode[T]
}
concurrentLinkedQueueIterator[T lang.Object] struct {
node *concurrentLinkedStackNode[T]
queue *ConcurrentLinkedQueue[T]
}
)
type concurrentLinkedQueueIterator[T any] struct {
head *concurrentLinkedQueueNode[T]
node *concurrentLinkedQueueNode[T]
func (q *ConcurrentLinkedQueue[T]) String() string {
return String[T](q)
}
func NewConcurrentLinkedQueue[T lang.Object]() *ConcurrentLinkedQueue[T] {
head := &concurrentLinkedQueueNode[T]{}
head.prev = head
head.next = head
return &ConcurrentLinkedQueue[T]{lang.NewBaseObject(), head}
return &ConcurrentLinkedQueue[T]{}
}
func (c *ConcurrentLinkedQueue[T]) Iterator() Iterator[T] {
return c.MutableIterator()
func (q *ConcurrentLinkedQueue[T]) Iterator() Iterator[T] {
return q.MutableIterator()
}
func (c *ConcurrentLinkedQueue[T]) Push(element T) exceptions.Exception {
newNode := &concurrentLinkedQueueNode[T]{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
func (q *ConcurrentLinkedQueue[T]) Offer(element T) exceptions.Exception {
_, err := q.offerAndGetNode(element)
return err
}
func (q *ConcurrentLinkedQueue[T]) OfferAndGetNode(element T) (ConcurrentLinkedQueueNode[T], exceptions.Exception) {
newNode, err := q.offerAndGetNode(element)
if err != nil {
return nil, err
}
atomic.CompareAndSwapPointer(
(*unsafe.Pointer)(unsafe.Pointer(&newNode.prev.next)),
unsafe.Pointer(&*c.head),
unsafe.Pointer(newNode),
)
return nil
return &concurrentLinkedQueueIterator[T]{queue: q, node: newNode}, nil
}
func (c *ConcurrentLinkedQueue[T]) Offer() (T, exceptions.Exception) {
next := c.head.next
if next == c.head {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
func (q *ConcurrentLinkedQueue[T]) offerAndGetNode(element T) (*concurrentLinkedStackNode[T], exceptions.Exception) {
newNode := &concurrentLinkedStackNode[T]{value: element}
q.size.Add(1)
var next **concurrentLinkedStackNode[T]
ref := q.end
switch {
case ref == nil:
next = &q.head
default:
next = &ref.next
}
p := (*unsafe.Pointer)(unsafe.Pointer(&next.next.prev))
if !next.removeNode(p) {
next = c.head.next
p = (*unsafe.Pointer)(unsafe.Pointer(&next.prev))
if next == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
for !atomic.CompareAndSwapPointer(next, nil, newNode) {
if ref == nil || ref.next == nil {
next = &q.head
ref = q.head
} else {
for ref.next != nil {
ref = ref.next
}
next = &ref.next
}
}
return next.value, nil
q.end = newNode
return newNode, nil
}
func (node *concurrentLinkedQueueNode[T]) 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 (q *ConcurrentLinkedQueue[T]) Poll() (T, exceptions.Exception) {
return q.Pop()
}
func (c *ConcurrentLinkedQueue[T]) MutableIterator() MutableIterator[T] {
return &concurrentLinkedQueueIterator[T]{c.head, c.head}
func (q *ConcurrentLinkedQueue[T]) MutableIterator() MutableIterator[T] {
return &concurrentLinkedQueueIterator[T]{node: q.head}
}
func (c *concurrentLinkedQueueIterator[T]) HasNext() bool {
return c.node.next != c.head
func (q *ConcurrentLinkedQueue[T]) Size() int {
return int(q.size.Load())
}
func (c *concurrentLinkedQueueIterator[T]) Next() (T, exceptions.Exception) {
c.node = c.node.next
if c.node == c.head {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
return c.node.value, nil
func (q *ConcurrentLinkedQueue[T]) IsEmpty() bool {
return q.head == nil
}
func (c *concurrentLinkedQueueIterator[T]) Remove() exceptions.Exception {
if c.node == c.head {
return exceptions.NewIndexOutOfBound("", nil)
}
c.node.removeNode(nil)
c.node = c.node.prev
return nil
func (q *ConcurrentLinkedQueue[T]) Contains(element T) bool {
return Contains[T](q, element)
}
func (c *ConcurrentLinkedQueue[T]) Size() int {
size, err := Size[T](c)
exceptions.Print(err)
return size
func (q *ConcurrentLinkedQueue[T]) ContainsAll(collection Collection[T]) bool {
return ContainsAll[T](q, collection)
}
func (c *ConcurrentLinkedQueue[T]) IsEmpty() bool {
return c.head.next == c.head
}
func (c *ConcurrentLinkedQueue[T]) Contains(element T) bool {
return Contains[T](c, element)
}
func (c *ConcurrentLinkedQueue[T]) ContainsAll(collection Collection[T]) bool {
return ContainsAll[T](c, collection)
}
func (c *ConcurrentLinkedQueue[T]) Add(element T) bool {
exception := c.Push(element)
func (q *ConcurrentLinkedQueue[T]) Add(element T) bool {
exception := q.Push(element)
exceptions.Print(exception)
return exception == nil
}
func (c *ConcurrentLinkedQueue[T]) Remove(element T) exceptions.Exception {
return Remove[T](c, element)
func (q *ConcurrentLinkedQueue[T]) Remove(element T) exceptions.Exception {
return Remove[T](q, element)
}
func (c *ConcurrentLinkedQueue[T]) AddAll(collection Collection[T]) bool {
return AddAll[T](c, collection)
func (q *ConcurrentLinkedQueue[T]) AddAll(collection Collection[T]) bool {
return AddAll[T](q, collection)
}
func (c *ConcurrentLinkedQueue[T]) RemoveAll(collection Collection[T]) bool {
return RemoveAll[T](c, collection)
func (q *ConcurrentLinkedQueue[T]) RemoveAll(collection Collection[T]) bool {
return RemoveAll[T](q, collection)
}
func (c *ConcurrentLinkedQueue[T]) RetainAll(collection Collection[T]) bool {
return RetainAll[T](c, collection)
func (q *ConcurrentLinkedQueue[T]) RetainAll(collection Collection[T]) bool {
return RetainAll[T](q, collection)
}
func (c *ConcurrentLinkedQueue[T]) Clear() {
head := &concurrentLinkedQueueNode[T]{}
head.prev = head
head.next = head
c.head = head
func (q *ConcurrentLinkedQueue[T]) Clear() {
q.head = nil
q.end = nil
q.size.Store(0)
}
func (i *concurrentLinkedQueueIterator[T]) HasNext() bool {
for i.node != nil && i.node.deleted {
i.node = i.node.next
}
return i.node != nil
}
func (i *concurrentLinkedQueueIterator[T]) Next() (T, exceptions.Exception) {
value, err := i.Get()
i.node = i.node.next
for i.node != nil && i.node.deleted {
i.node = i.node.next
}
return value, err
}
func (i *concurrentLinkedQueueIterator[T]) Get() (T, exceptions.Exception) {
return (*i.node).value, nil
}
func (i *concurrentLinkedQueueIterator[T]) Remove() exceptions.Exception {
_, err := i.RemoveAndGet()
return err
}
func (i *concurrentLinkedQueueIterator[T]) RemoveAndGet() (T, exceptions.Exception) {
if i.node == nil {
return lang.Nil[T](), nil
}
load := i.node
load.deleted = true
i.queue.size.Add(-1)
i.queue.deleted.Add(1)
i.queue.CleanDeleted()
i.node = load.next
return load.value, nil
}

View File

@ -0,0 +1,97 @@
package collections
import (
"fmt"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"sync"
"testing"
"time"
"unsafe"
)
type data struct {
lang.BaseObject
id int
index int
}
func (d *data) String() string {
return fmt.Sprintf("(%d,%d)", d.id, d.index)
}
func TestConcurrentLinkedQueue_NodeSize(t *testing.T) {
fmt.Println(unsafe.Alignof(concurrentLinkedStackNode[*data]{}))
fmt.Println(unsafe.Sizeof(concurrentLinkedStackNode[*data]{}))
}
func TestConcurrentLinkedQueue_Push(t *testing.T) {
queue := NewConcurrentLinkedQueue[*data]()
cond := sync.WaitGroup{}
cond.Add(1)
for i := 0; i < 10; i++ {
id := i
go func() {
cond.Wait()
for i := 0; i < 100; i++ {
_ = queue.Offer(&data{id: id, index: i})
}
}()
}
time.Sleep(time.Second)
cond.Done()
time.Sleep(time.Second)
fmt.Println(queue)
}
func TestConcurrentLinkedQueue_ThreadSafe(t *testing.T) {
times := 400000
queue := NewConcurrentLinkedQueue[*data]()
for i := 0; i < 100; i++ {
id := i
go func() {
//nodes := make([]ConcurrentLinkedQueueNode[*data], 0)
for j := 0; j < times; j++ {
_ = queue.Offer(&data{id: id, index: j})
//node, _ := queue.OfferAndGetNode(&data{id: id, index: j})
//nodes = append(nodes, node)
//fmt.Println(queue)
}
//time.Sleep(time.Second * 1)
fmt.Println(queue.Size())
//for _, node := range nodes {
// exceptions.Exec0r0(node.Remove)
//}
for j := 0; j < times; j++ {
offer, _ := queue.Poll()
if offer == nil {
panic("offer is nil")
}
}
}()
}
time.Sleep(time.Second * 10)
if queue.Size() != 0 {
t.Fatalf(fmt.Sprintf("queue remain %d element, is not thread safe", queue.Size()))
}
//for !queue.IsEmpty() {
// fmt.Println(queue.Offer())
//}
}
func Test_concurrentLinkedQueueIterator_Remove(t *testing.T) {
queue := NewConcurrentLinkedQueue[lang.Int]()
nodes := make([]ConcurrentLinkedQueueNode[lang.Int], 0)
for i := 0; i < 1000; i++ {
node, _ := queue.OfferAndGetNode(lang.Int(i))
nodes = append(nodes, node)
//fmt.Println(queue)
}
for _, node := range nodes {
fmt.Println(exceptions.Exec0r1(node.RemoveAndGet))
}
if queue.Size() != 0 {
t.Fatalf(fmt.Sprintf("queue remain %d element, is not thread safe", queue.Size()))
}
}

View File

@ -3,89 +3,146 @@ package collections
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"sync/atomic"
"unsafe"
"github.com/tursom/GoCollections/lang/atomic"
)
type ConcurrentLinkedStack[T any] struct {
lang.BaseObject
head *concurrentLinkedStackNode[T]
p *unsafe.Pointer
}
func (c ConcurrentLinkedStack[T]) String() string {
return String[T](c)
}
type concurrentLinkedStackNode[T any] struct {
value T
next *concurrentLinkedStackNode[T]
}
type concurrentLinkedStackIterator[T any] struct {
node *concurrentLinkedStackNode[T]
prev *concurrentLinkedStackNode[T]
}
func NewConcurrentLinkedStack[T any]() *ConcurrentLinkedStack[T] {
head := &concurrentLinkedStackNode[T]{}
return &ConcurrentLinkedStack[T]{lang.NewBaseObject(), head, (*unsafe.Pointer)(unsafe.Pointer(&head.next))}
}
func (c ConcurrentLinkedStack[T]) Iterator() Iterator[T] {
return c.MutableIterator()
}
func (c *ConcurrentLinkedStack[T]) Push(element T) exceptions.Exception {
newNode := &concurrentLinkedStackNode[T]{element, c.head.next}
np := unsafe.Pointer(newNode)
for !atomic.CompareAndSwapPointer(c.p, unsafe.Pointer(&*newNode.next), np) {
type (
ConcurrentLinkedStack[T lang.Object] struct {
lang.BaseObject
size atomic.Int32
deleted atomic.Int32
head *concurrentLinkedStackNode[T]
}
concurrentLinkedStackNode[T any] struct {
deleted bool
next *concurrentLinkedStackNode[T]
value T
}
concurrentLinkedStackIterator[T lang.Object] struct {
node *concurrentLinkedStackNode[T]
stack *ConcurrentLinkedStack[T]
}
)
func (s *ConcurrentLinkedStack[T]) String() string {
return String[T](s)
}
func NewConcurrentLinkedStack[T lang.Object]() *ConcurrentLinkedStack[T] {
return &ConcurrentLinkedStack[T]{}
}
func (s *ConcurrentLinkedStack[T]) Iterator() Iterator[T] {
return s.MutableIterator()
}
func (s *ConcurrentLinkedStack[T]) Push(element T) exceptions.Exception {
newNode := &concurrentLinkedStackNode[T]{value: element, next: s.head}
for !atomic.CompareAndSwapPointer(&s.head, newNode.next, newNode) {
newNode.next = s.head
}
s.size.Add(1)
return nil
}
func (c *ConcurrentLinkedStack[T]) Pop() (T, exceptions.Exception) {
next := c.head.next
if next == nil {
func (s *ConcurrentLinkedStack[T]) Pop() (T, exceptions.Exception) {
node := s.head
for node != nil && (!atomic.CompareAndSwapPointer(&s.head, node, node.next) || node.deleted) {
node = s.head
}
if node == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
p := (*unsafe.Pointer)(unsafe.Pointer(&c.head.next))
s.size.Add(-1)
return node.value, nil
}
if !atomic.CompareAndSwapPointer(p, unsafe.Pointer(&*next), unsafe.Pointer(&*next.next)) {
next = c.head.next
if next == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
func (s *ConcurrentLinkedStack[T]) CleanDeleted() {
if s.deleted.Load() <= s.size.Load() {
return
}
s.deleted.Store(0)
node := &s.head
for node != nil && *node != nil {
if (*node).deleted {
atomic.CompareAndSwapPointer(node, *node, (*node).next)
} else {
node = &(*node).next
}
}
return next.value, nil
}
func (c *ConcurrentLinkedStack[T]) MutableIterator() MutableIterator[T] {
return &concurrentLinkedStackIterator[T]{c.head, nil}
func (s *ConcurrentLinkedStack[T]) Size() int {
return int(s.size.Load())
}
func (c *concurrentLinkedStackIterator[T]) HasNext() bool {
return c.node.next != nil
func (s *ConcurrentLinkedStack[T]) IsEmpty() bool {
return s.head == nil
}
func (c *concurrentLinkedStackIterator[T]) Next() (T, exceptions.Exception) {
c.prev = c.node
c.node = c.node.next
if c.node == nil {
func (s *ConcurrentLinkedStack[T]) Contains(element T) bool {
return Contains[T](s, element)
}
func (s *ConcurrentLinkedStack[T]) ContainsAll(c Collection[T]) bool {
return ContainsAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) Add(element T) bool {
exception := s.Push(element)
exceptions.Print(exception)
return exception == nil
}
func (s *ConcurrentLinkedStack[T]) Remove(element T) exceptions.Exception {
return Remove[T](s, element)
}
func (s *ConcurrentLinkedStack[T]) AddAll(c Collection[T]) bool {
return AddAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) RemoveAll(c Collection[T]) bool {
return RemoveAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) RetainAll(c Collection[T]) bool {
return RetainAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) Clear() {
s.head = nil
s.size.Store(0)
}
func (s *ConcurrentLinkedStack[T]) MutableIterator() MutableIterator[T] {
return &concurrentLinkedStackIterator[T]{s.head, nil}
}
func (i *concurrentLinkedStackIterator[T]) HasNext() bool {
return i.node.next != nil
}
func (i *concurrentLinkedStackIterator[T]) Next() (T, exceptions.Exception) {
if i.node == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
return c.node.value, nil
value := i.node.value
i.node = i.node.next
return value, nil
}
func (c *concurrentLinkedStackIterator[T]) Remove() exceptions.Exception {
if c.node == nil {
func (i *concurrentLinkedStackIterator[T]) Remove() exceptions.Exception {
if i.node == nil {
return exceptions.NewIndexOutOfBound("", nil)
}
next := c.node.next
p := (*unsafe.Pointer)(unsafe.Pointer(&c.prev.next))
atomic.CompareAndSwapPointer(p, unsafe.Pointer(&*c.node), unsafe.Pointer(&*next))
i.node.deleted = true
i.node = i.node.next
i.stack.size.Add(-1)
i.stack.deleted.Add(1)
i.stack.CleanDeleted()
return nil
}

View File

@ -0,0 +1,126 @@
package collections
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type (
CopyOnWriteList[E lang.Object] struct {
lang.BaseObject
arr []E
}
copyOnWriteListIterator[E lang.Object] struct {
lang.BaseObject
list *CopyOnWriteList[E]
arr []E
index int
}
)
func (l *CopyOnWriteList[E]) Iterator() Iterator[E] {
return l.MutableIterator()
}
func (l *CopyOnWriteList[E]) Size() int {
return len(l.arr)
}
func (l *CopyOnWriteList[E]) IsEmpty() bool {
return l.Size() == 0
}
func (l *CopyOnWriteList[E]) Contains(element E) bool {
return Contains[E](l, element)
}
func (l *CopyOnWriteList[E]) ContainsAll(c Collection[E]) bool {
return ContainsAll[E](l, c)
}
func (l *CopyOnWriteList[E]) MutableIterator() MutableIterator[E] {
return &copyOnWriteListIterator[E]{
list: l,
arr: l.arr,
index: 0,
}
}
func (l *CopyOnWriteList[E]) Add(element E) bool {
l.arr = append(l.arr, element)
return true
}
func (l *CopyOnWriteList[E]) Remove(element E) exceptions.Exception {
return Remove[E](l, element)
}
func (l *CopyOnWriteList[E]) AddAll(c Collection[E]) bool {
_ = Loop[E](c, func(element E) exceptions.Exception {
l.arr = append(l.arr, element)
return nil
})
return true
}
func (l *CopyOnWriteList[E]) RemoveAll(c Collection[E]) bool {
return RemoveAll[E](l, c)
}
func (l *CopyOnWriteList[E]) RetainAll(c Collection[E]) bool {
return RetainAll[E](l, c)
}
func (l *CopyOnWriteList[E]) Clear() {
l.arr = make([]E, 0)
}
func (l *CopyOnWriteList[E]) Get(index int) (E, exceptions.Exception) {
if index < 0 || index >= l.Size() {
return lang.Nil[E](), exceptions.NewIndexOutOfBound("", nil)
}
return l.arr[index], nil
}
func (l *CopyOnWriteList[E]) SubList(from, to int) List[E] {
return l.SubList(from, to)
}
func (l *CopyOnWriteList[E]) Set(index int, element E) exceptions.Exception {
if index < 0 || index >= l.Size() {
return exceptions.NewIndexOutOfBound("", nil)
}
l.arr[index] = element
return nil
}
func (l *CopyOnWriteList[E]) AddAtIndex(index int, element E) bool {
//TODO implement me
panic("implement me")
}
func (l *CopyOnWriteList[E]) RemoveAt(index int) exceptions.Exception {
//TODO implement me
panic("implement me")
}
func (l *CopyOnWriteList[E]) SubMutableList(from, to int) MutableList[E] {
//TODO implement me
panic("implement me")
}
func (c *copyOnWriteListIterator[E]) HasNext() bool {
//TODO implement me
panic("implement me")
}
func (c *copyOnWriteListIterator[E]) Next() (E, exceptions.Exception) {
//TODO implement me
panic("implement me")
}
func (c *copyOnWriteListIterator[E]) Remove() exceptions.Exception {
//TODO implement me
panic("implement me")
}

View File

@ -13,13 +13,12 @@ type Iterable[T any] interface {
}
type MutableIterator[T any] interface {
HasNext() bool
Next() (T, exceptions.Exception)
Iterator[T]
Remove() exceptions.Exception
}
type MutableIterable[T any] interface {
Iterator() Iterator[T]
Iterable[T]
MutableIterator() MutableIterator[T]
}

View File

@ -6,11 +6,8 @@ import (
)
type Queue[T lang.Object] interface {
// Iterator MutableIterable
Iterator() Iterator[T]
// MutableIterator MutableIterable
MutableIterator() *linkedListIterator[T]
MutableIterable[T]
Push(element T) exceptions.Exception
Offer() (T, exceptions.Exception)
Offer(element T) exceptions.Exception
Poll() (T, exceptions.Exception)
}

View File

@ -3,10 +3,7 @@ package collections
import "github.com/tursom/GoCollections/exceptions"
type Stack[T any] interface {
// Iterator MutableIterable
Iterator() Iterator[T]
// MutableIterator MutableIterable
MutableIterator() MutableIterator[T]
MutableIterable[T]
Push(element T) exceptions.Exception
Pop() (T, exceptions.Exception)

View File

@ -10,6 +10,7 @@ import (
type Exception interface {
Cause() Exception
Error() string
ErrorMessage() string
StackTrace() []StackTrace
PrintStackTrace()
PrintStackTraceTo(writer io.Writer)
@ -46,7 +47,7 @@ func BuildStackTraceByArray(builder *strings.Builder, trace []StackTrace) {
}
func BuildStackTrace(builder *strings.Builder, e Exception, exceptionMsg string) {
builder.WriteString(fmt.Sprintln(exceptionMsg, e.Error()))
builder.WriteString(fmt.Sprintln(exceptionMsg, e.ErrorMessage()))
if e.StackTrace() == nil {
return
}

View File

@ -60,6 +60,10 @@ func (o RuntimeException) Error() string {
return builder.String()
}
func (o RuntimeException) ErrorMessage() string {
return o.exceptionMessage
}
func (o RuntimeException) StackTrace() []StackTrace {
return o.stackTrace
}

View File

@ -32,10 +32,10 @@ func Cast[T any](v any) T {
}
}
func ForceCast[T any](v *any) T {
func ForceCast[T any](v unsafe.Pointer) T {
if v == nil {
return Nil[T]()
} else {
return Cast[T](unsafe.Pointer(v))
return Cast[T](v)
}
}

37
lang/atomic/Bool.go Normal file
View File

@ -0,0 +1,37 @@
package atomic
type Bool struct {
i Int32
}
func (v *Bool) Load() (val bool) {
return v.i.Load() != 0
}
func (v *Bool) Store(val bool) {
if val {
v.i.Store(1)
} else {
v.i.Store(0)
}
}
func (v *Bool) Swap(new bool) (old bool) {
n := int32(0)
if new {
n = 1
}
return v.i.Swap(n) != 0
}
func (v *Bool) CompareAndSwap(old, new bool) (swapped bool) {
o := int32(0)
if old {
o = 1
}
n := int32(0)
if new {
n = 1
}
return v.i.CompareAndSwap(o, n)
}

29
lang/atomic/Int32.go Normal file
View File

@ -0,0 +1,29 @@
package atomic
import (
"sync/atomic"
)
type Int32 struct {
i int32
}
func (v *Int32) Load() (val int32) {
return atomic.LoadInt32(&v.i)
}
func (v *Int32) Store(val int32) {
atomic.StoreInt32(&v.i, val)
}
func (v *Int32) Swap(new int32) (old int32) {
return atomic.SwapInt32(&v.i, new)
}
func (v *Int32) CompareAndSwap(old, new int32) (swapped bool) {
return atomic.CompareAndSwapInt32(&v.i, old, new)
}
func (v *Int32) Add(i int32) (new int32) {
return atomic.AddInt32(&v.i, i)
}

29
lang/atomic/Int64.go Normal file
View File

@ -0,0 +1,29 @@
package atomic
import (
"sync/atomic"
)
type Int64 struct {
i int64
}
func (v *Int64) Load() (val int64) {
return atomic.LoadInt64(&v.i)
}
func (v *Int64) Store(val int64) {
atomic.StoreInt64(&v.i, val)
}
func (v *Int64) Swap(new int64) (old int64) {
return atomic.SwapInt64(&v.i, new)
}
func (v *Int64) CompareAndSwap(old, new int64) (swapped bool) {
return atomic.CompareAndSwapInt64(&v.i, old, new)
}
func (v *Int64) Add(i int64) (new int64) {
return atomic.AddInt64(&v.i, i)
}

46
lang/atomic/Reference.go Normal file
View File

@ -0,0 +1,46 @@
package atomic
import (
"sync/atomic"
"unsafe"
)
type Reference[T any] struct {
reference *T
}
func NewReference[T any](reference *T) *Reference[T] {
return &Reference[T]{reference}
}
func (v *Reference[T]) Load() (val *T) {
return LoadPointer(&v.reference)
}
func (v *Reference[T]) Store(val *T) {
StorePointer(&v.reference, val)
}
func (v *Reference[T]) Swap(new *T) (old *T) {
return SwapPointer(&v.reference, new)
}
func (v *Reference[T]) CompareAndSwap(old, new *T) (swapped bool) {
return CompareAndSwapPointer(&v.reference, old, new)
}
func LoadPointer[T any](addr **T) (val *T) {
return (*T)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(addr))))
}
func StorePointer[T any](addr **T, val *T) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(addr)), unsafe.Pointer(val))
}
func SwapPointer[T any](addr **T, new *T) (old *T) {
return (*T)(atomic.SwapPointer((*unsafe.Pointer)(unsafe.Pointer(addr)), unsafe.Pointer(new)))
}
func CompareAndSwapPointer[T any](addr **T, old, new *T) (swapped bool) {
return atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(addr)), unsafe.Pointer(old), unsafe.Pointer(new))
}

View File

@ -0,0 +1,15 @@
package atomic
import (
"fmt"
"github.com/tursom/GoCollections/lang"
"testing"
)
func TestAtomic_Store(t *testing.T) {
a := &Reference[lang.Int]{}
var i lang.Int = 1
a.Store(&i)
i = 2
fmt.Println(a.Load())
}

29
lang/atomic/UInt32.go Normal file
View File

@ -0,0 +1,29 @@
package atomic
import (
"sync/atomic"
)
type UInt32 struct {
i uint32
}
func (v *UInt32) Load() (val uint32) {
return atomic.LoadUint32(&v.i)
}
func (v *UInt32) Store(val uint32) {
atomic.StoreUint32(&v.i, val)
}
func (v *UInt32) Swap(new uint32) (old uint32) {
return atomic.SwapUint32(&v.i, new)
}
func (v *UInt32) CompareAndSwap(old, new uint32) (swapped bool) {
return atomic.CompareAndSwapUint32(&v.i, old, new)
}
func (v *UInt32) Add(i uint32) (new uint32) {
return atomic.AddUint32(&v.i, i)
}

29
lang/atomic/UInt64.go Normal file
View File

@ -0,0 +1,29 @@
package atomic
import (
"sync/atomic"
)
type UInt64 struct {
i uint64
}
func (v *UInt64) Load() (val uint64) {
return atomic.LoadUint64(&v.i)
}
func (v *UInt64) Store(val uint64) {
atomic.StoreUint64(&v.i, val)
}
func (v *UInt64) Swap(new uint64) (old uint64) {
return atomic.SwapUint64(&v.i, new)
}
func (v *UInt64) CompareAndSwap(old, new uint64) (swapped bool) {
return atomic.CompareAndSwapUint64(&v.i, old, new)
}
func (v *UInt64) Add(i uint64) (new uint64) {
return atomic.AddUint64(&v.i, i)
}