github.com/Nigel2392/go-datastructures@v1.1.5/stack/stack.go (about)

     1  package stack
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/Nigel2392/go-datastructures/linkedlist"
     8  )
     9  
    10  // Stack is a stack data structure
    11  //
    12  // # It is implemeneted using a singly linked list
    13  //
    14  // # This is to save space, as the stack only needs to know about the top element
    15  //
    16  // This does mean that the data gets prepended at the start, and then shifted off,
    17  // as opposed to appended and then popped off.
    18  type Stack[T any] linkedlist.Singly[T]
    19  
    20  // Push adds a value to the top of the stack
    21  //
    22  // This is the same as Prepend in a linked list
    23  func (s *Stack[T]) Push(value T) {
    24  	(*linkedlist.Singly[T])(s).Prepend(value)
    25  }
    26  
    27  // Pop removes a value from the top of the stack
    28  //
    29  // This is the same as Shift in a linked list
    30  func (s *Stack[T]) Pop() T {
    31  	return (*linkedlist.Singly[T])(s).Shift()
    32  }
    33  
    34  // PopOK removes a value from the top of the stack
    35  //
    36  // # This is the same as Shift in a linked list
    37  //
    38  // It returns the value and a boolean indicating whether the value was removed
    39  func (s *Stack[T]) PopOK() (value T, ok bool) {
    40  	if s.Len() == 0 {
    41  		return
    42  	}
    43  	return (*linkedlist.Singly[T])(s).Shift(), true
    44  }
    45  
    46  // PopWaiter allows you to wait on a value through a channel.
    47  func (s *Stack[T]) PopWaiter(sleep time.Duration) <-chan T {
    48  	var c = make(chan T, 1)
    49  	var mu = new(sync.Mutex)
    50  	go s.wait(mu, c, sleep)
    51  	return c
    52  }
    53  
    54  func (s *Stack[T]) wait(mu *sync.Mutex, c chan<- T, sleep time.Duration) {
    55  	for {
    56  		if s.Len() > 0 {
    57  			mu.Lock()
    58  			// Check again to make sure it wasn't removed
    59  			if s.Len() <= 0 {
    60  				mu.Unlock()
    61  				continue
    62  			}
    63  			c <- (*linkedlist.Singly[T])(s).Shift()
    64  			close(c)
    65  			mu.Unlock()
    66  			return
    67  		}
    68  		if sleep > 0 {
    69  			time.Sleep(sleep)
    70  		}
    71  	}
    72  }
    73  
    74  // PopOKDeadline returns a channel where the value will be sent when it is available
    75  func (s *Stack[T]) PopOKDeadline(deadline time.Duration) (ret <-chan T, ok <-chan time.Time) {
    76  	var deadlineWaiter = time.After(deadline)
    77  	var c = make(chan T, 1)
    78  	var mu = new(sync.Mutex)
    79  	go func(mut *sync.Mutex) {
    80  		for {
    81  			select {
    82  			case <-deadlineWaiter:
    83  				close(c)
    84  				return
    85  			default:
    86  				if s.Len() > 0 {
    87  					mut.Lock()
    88  					defer mut.Unlock()
    89  					if s.Len() > 0 {
    90  						c <- (*linkedlist.Singly[T])(s).Shift()
    91  						close(c)
    92  						return
    93  					}
    94  				}
    95  			}
    96  		}
    97  	}(mu)
    98  
    99  	return c, deadlineWaiter
   100  
   101  }
   102  
   103  // Peek returns the value at the top of the stack
   104  //
   105  // This is the same as Head in a linked list
   106  func (s *Stack[T]) Peek() (value T) {
   107  	var head = (*linkedlist.Singly[T])(s).Head()
   108  	if head == nil {
   109  		return // value is zero value
   110  	}
   111  	return head.Value()
   112  }
   113  
   114  func (s *Stack[T]) Len() int {
   115  	return (*linkedlist.Singly[T])(s).Len()
   116  }