80 lines
1.5 KiB
Go
80 lines
1.5 KiB
Go
package ds_utils
|
|
|
|
import "sync"
|
|
|
|
type IStack[T any] interface {
|
|
Push(item T)
|
|
Get() T
|
|
Len() int
|
|
}
|
|
|
|
// This queue isn't suppose to be thread safe
|
|
// If you will try to get item from an empty queue -- it will panic
|
|
// (Because if u have single-threaded app and one thread will be locked
|
|
// by getting an item from the queue, there will be no thread to put that item)
|
|
// For multythreaded usage -- use StackSync (it's calm, never panics)
|
|
type Stack[T any] struct {
|
|
IStack[T]
|
|
Buffer []T
|
|
}
|
|
|
|
func NewStack[T any]() *Stack[T] {
|
|
return &Stack[T]{}
|
|
}
|
|
|
|
func (q *Stack[T]) Push(item T) {
|
|
q.Buffer = append(q.Buffer, item)
|
|
}
|
|
|
|
func (q *Stack[T]) Get() T {
|
|
if len(q.Buffer) < 1 {
|
|
panic("Trying to get from an empty thread unsafe queue")
|
|
}
|
|
item := q.Buffer[len(q.Buffer)-1]
|
|
q.Buffer = q.Buffer[:len(q.Buffer)-1]
|
|
return item
|
|
}
|
|
|
|
func (q *Stack[T]) Len() int {
|
|
return len(q.Buffer)
|
|
}
|
|
|
|
// Stack sync
|
|
type StackSync[T any] struct {
|
|
IStack[T]
|
|
Buffer []T
|
|
Mu *sync.Mutex
|
|
NonEmptyCond *sync.Cond
|
|
}
|
|
|
|
func NewStackSync[T any]() *StackSync[T] {
|
|
return &StackSync[T]{
|
|
Mu: &sync.Mutex{},
|
|
NonEmptyCond: sync.NewCond(&sync.RWMutex{}),
|
|
}
|
|
}
|
|
|
|
func (q *StackSync[T]) Push(item T) {
|
|
q.Mu.Lock()
|
|
q.Buffer = append(q.Buffer, item)
|
|
q.NonEmptyCond.Signal()
|
|
q.Mu.Unlock()
|
|
}
|
|
|
|
func (q *StackSync[T]) Get() T {
|
|
q.Mu.Lock()
|
|
if len(q.Buffer) < 1 {
|
|
q.NonEmptyCond.Wait()
|
|
}
|
|
item := q.Buffer[len(q.Buffer)-1]
|
|
q.Buffer = q.Buffer[:len(q.Buffer)-1]
|
|
q.Mu.Unlock()
|
|
return item
|
|
}
|
|
|
|
func (q *StackSync[T]) Len() int {
|
|
q.Mu.Lock()
|
|
defer q.Mu.Lock()
|
|
return len(q.Buffer)
|
|
}
|