diff --git a/collections/ArrayList.go b/collections/ArrayList.go index d804f27..933e73f 100644 --- a/collections/ArrayList.go +++ b/collections/ArrayList.go @@ -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() } diff --git a/collections/Collection.go b/collections/Collection.go index eec87b4..79108e6 100644 --- a/collections/Collection.go +++ b/collections/Collection.go @@ -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 diff --git a/collections/ConcurrentLinkedQueue.go b/collections/ConcurrentLinkedQueue.go index b32ee3f..7bd6103 100644 --- a/collections/ConcurrentLinkedQueue.go +++ b/collections/ConcurrentLinkedQueue.go @@ -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 } diff --git a/collections/ConcurrentLinkedQueue_test.go b/collections/ConcurrentLinkedQueue_test.go new file mode 100644 index 0000000..8259db1 --- /dev/null +++ b/collections/ConcurrentLinkedQueue_test.go @@ -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())) + } +} diff --git a/collections/ConcurrentLinkedStack.go b/collections/ConcurrentLinkedStack.go index 77a8111..d004484 100644 --- a/collections/ConcurrentLinkedStack.go +++ b/collections/ConcurrentLinkedStack.go @@ -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 } diff --git a/collections/CopyOnWriteList.go b/collections/CopyOnWriteList.go new file mode 100644 index 0000000..074ceb4 --- /dev/null +++ b/collections/CopyOnWriteList.go @@ -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 ©OnWriteListIterator[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") +} diff --git a/collections/Iterable.go b/collections/Iterable.go index 33d971a..a2e30e7 100644 --- a/collections/Iterable.go +++ b/collections/Iterable.go @@ -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] } diff --git a/collections/Queue.go b/collections/Queue.go index e0c31e4..fa03da5 100644 --- a/collections/Queue.go +++ b/collections/Queue.go @@ -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) } diff --git a/collections/Stack.go b/collections/Stack.go index ba0a6a9..b326e1c 100644 --- a/collections/Stack.go +++ b/collections/Stack.go @@ -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) diff --git a/exceptions/Exception.go b/exceptions/Exception.go index 01037e4..fde6498 100644 --- a/exceptions/Exception.go +++ b/exceptions/Exception.go @@ -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 } diff --git a/exceptions/RuntimeException.go b/exceptions/RuntimeException.go index fb98eeb..15af254 100644 --- a/exceptions/RuntimeException.go +++ b/exceptions/RuntimeException.go @@ -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 } diff --git a/lang/Lang.go b/lang/Lang.go index 7e47d69..b37a3f4 100644 --- a/lang/Lang.go +++ b/lang/Lang.go @@ -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) } } diff --git a/lang/atomic/Bool.go b/lang/atomic/Bool.go new file mode 100644 index 0000000..f8d6663 --- /dev/null +++ b/lang/atomic/Bool.go @@ -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) +} diff --git a/lang/atomic/Int32.go b/lang/atomic/Int32.go new file mode 100644 index 0000000..b45c4f3 --- /dev/null +++ b/lang/atomic/Int32.go @@ -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) +} diff --git a/lang/atomic/Int64.go b/lang/atomic/Int64.go new file mode 100644 index 0000000..a5a1b23 --- /dev/null +++ b/lang/atomic/Int64.go @@ -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) +} diff --git a/lang/atomic/Reference.go b/lang/atomic/Reference.go new file mode 100644 index 0000000..dc9baee --- /dev/null +++ b/lang/atomic/Reference.go @@ -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)) +} diff --git a/lang/atomic/Reference_test.go b/lang/atomic/Reference_test.go new file mode 100644 index 0000000..10fe162 --- /dev/null +++ b/lang/atomic/Reference_test.go @@ -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()) +} diff --git a/lang/atomic/UInt32.go b/lang/atomic/UInt32.go new file mode 100644 index 0000000..067d8d7 --- /dev/null +++ b/lang/atomic/UInt32.go @@ -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) +} diff --git a/lang/atomic/UInt64.go b/lang/atomic/UInt64.go new file mode 100644 index 0000000..cb2473e --- /dev/null +++ b/lang/atomic/UInt64.go @@ -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) +}