github.com/tursom/GoCollections@v0.3.10/concurrent/collections/ConcurrentLinkedStack.go (about)

     1  /*
     2   * Copyright (c) 2022 tursom. All rights reserved.
     3   * Use of this source code is governed by a GPL-3
     4   * license that can be found in the LICENSE file.
     5   */
     6  
     7  package collections
     8  
     9  import (
    10  	"github.com/tursom/GoCollections/collections"
    11  	"github.com/tursom/GoCollections/exceptions"
    12  	"github.com/tursom/GoCollections/lang"
    13  	"github.com/tursom/GoCollections/lang/atomic"
    14  )
    15  
    16  type (
    17  	ConcurrentLinkedStack[T lang.Object] struct {
    18  		lang.BaseObject
    19  		size    atomic.Int32
    20  		deleted atomic.Int32
    21  		head    *linkedStackNode[T]
    22  	}
    23  
    24  	linkedStackNode[T any] struct {
    25  		deleted bool
    26  		next    *linkedStackNode[T]
    27  		value   T
    28  	}
    29  
    30  	linkedStackIterator[T lang.Object] struct {
    31  		node  *linkedStackNode[T]
    32  		stack *ConcurrentLinkedStack[T]
    33  	}
    34  )
    35  
    36  func (s *ConcurrentLinkedStack[T]) String() string {
    37  	return collections.String[T](s)
    38  }
    39  
    40  func NewLinkedStack[T lang.Object]() *ConcurrentLinkedStack[T] {
    41  	return &ConcurrentLinkedStack[T]{}
    42  }
    43  
    44  func (s *ConcurrentLinkedStack[T]) Iterator() collections.Iterator[T] {
    45  	return s.MutableIterator()
    46  }
    47  
    48  func (s *ConcurrentLinkedStack[T]) Push(element T) exceptions.Exception {
    49  	s.push(element)
    50  	return nil
    51  }
    52  
    53  func (s *ConcurrentLinkedStack[T]) PushAndGetNode(element T) collections.StackNode[T] {
    54  	return &linkedStackIterator[T]{
    55  		node:  s.push(element),
    56  		stack: s,
    57  	}
    58  }
    59  
    60  func (s *ConcurrentLinkedStack[T]) push(element T) *linkedStackNode[T] {
    61  	newNode := &linkedStackNode[T]{value: element, next: s.head}
    62  	for !atomic.CompareAndSwapPointer(&s.head, newNode.next, newNode) {
    63  		newNode.next = s.head
    64  	}
    65  	s.size.Add(1)
    66  	return newNode
    67  }
    68  
    69  func (s *ConcurrentLinkedStack[T]) Pop() (T, exceptions.Exception) {
    70  	node := s.head
    71  	for node != nil && (!atomic.CompareAndSwapPointer(&s.head, node, node.next) || node.deleted) {
    72  		node = s.head
    73  	}
    74  	if node == nil {
    75  		return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
    76  	}
    77  
    78  	s.size.Add(-1)
    79  	return node.value, nil
    80  }
    81  
    82  // CleanDeleted tell stack that may clean deleted nodes
    83  func (s *ConcurrentLinkedStack[T]) CleanDeleted() {
    84  	if s.deleted.Load() <= s.size.Load() {
    85  		return
    86  	}
    87  	s.deleted.Store(0)
    88  	node := &s.head
    89  	for node != nil && *node != nil {
    90  		if (*node).deleted {
    91  			atomic.CompareAndSwapPointer(node, *node, (*node).next)
    92  		} else {
    93  			node = &(*node).next
    94  		}
    95  	}
    96  }
    97  
    98  func (s *ConcurrentLinkedStack[T]) Size() int {
    99  	return int(s.size.Load())
   100  }
   101  
   102  func (s *ConcurrentLinkedStack[T]) IsEmpty() bool {
   103  	return s.head == nil
   104  }
   105  
   106  func (s *ConcurrentLinkedStack[T]) Contains(element T) bool {
   107  	return collections.Contains[T](s, element)
   108  }
   109  
   110  func (s *ConcurrentLinkedStack[T]) ContainsAll(c collections.Collection[T]) bool {
   111  	return collections.ContainsAll[T](s, c)
   112  }
   113  
   114  func (s *ConcurrentLinkedStack[T]) Add(element T) bool {
   115  	exception := s.Push(element)
   116  	exceptions.Print(exception)
   117  	return exception == nil
   118  }
   119  
   120  func (s *ConcurrentLinkedStack[T]) Remove(element T) exceptions.Exception {
   121  	return collections.Remove[T](s, element)
   122  }
   123  
   124  func (s *ConcurrentLinkedStack[T]) AddAll(c collections.Collection[T]) bool {
   125  	return collections.AddAll[T](s, c)
   126  }
   127  
   128  func (s *ConcurrentLinkedStack[T]) RemoveAll(c collections.Collection[T]) bool {
   129  	return collections.RemoveAll[T](s, c)
   130  }
   131  
   132  func (s *ConcurrentLinkedStack[T]) RetainAll(c collections.Collection[T]) bool {
   133  	return collections.RetainAll[T](s, c)
   134  }
   135  
   136  func (s *ConcurrentLinkedStack[T]) Clear() {
   137  	s.head = nil
   138  	s.size.Store(0)
   139  }
   140  
   141  func (s *ConcurrentLinkedStack[T]) MutableIterator() collections.MutableIterator[T] {
   142  	return &linkedStackIterator[T]{s.head, nil}
   143  }
   144  
   145  func (i *linkedStackIterator[T]) HasNext() bool {
   146  	return i.node.next != nil
   147  }
   148  
   149  func (i *linkedStackIterator[T]) Next() (T, exceptions.Exception) {
   150  	if i.node == nil {
   151  		return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
   152  	}
   153  	value := i.node.value
   154  	i.node = i.node.next
   155  	return value, nil
   156  }
   157  
   158  func (i *linkedStackIterator[T]) Remove() exceptions.Exception {
   159  	if i.node == nil {
   160  		return exceptions.NewIndexOutOfBound("", nil)
   161  	}
   162  	i.node.deleted = true
   163  	i.node = i.node.next
   164  	i.stack.size.Add(-1)
   165  	i.stack.deleted.Add(1)
   166  	i.stack.CleanDeleted()
   167  	return nil
   168  }
   169  
   170  func (i *linkedStackIterator[T]) Get() (T, exceptions.Exception) {
   171  	return i.node.value, nil
   172  }
   173  
   174  func (i *linkedStackIterator[T]) Set(value T) exceptions.Exception {
   175  	i.node.value = value
   176  	return nil
   177  }
   178  
   179  func (i *linkedStackIterator[T]) RemoveAndGet() (T, exceptions.Exception) {
   180  	i.node.deleted = true
   181  	return i.node.value, nil
   182  }