84 lines
1.5 KiB
Go
84 lines
1.5 KiB
Go
package dsUtils
|
|
|
|
import (
|
|
"io"
|
|
"sync"
|
|
)
|
|
|
|
type IQueue[T any] interface {
|
|
Push(item T)
|
|
Get() T
|
|
Len() int
|
|
}
|
|
|
|
// Queue isn't thread safe and suppose to be used only in a single thread
|
|
// For multithreaded usage -- use QueueSync
|
|
type Queue[T any] struct {
|
|
IQueue[T]
|
|
Buffer []T
|
|
}
|
|
|
|
// NewQueue creates a new Queue instance
|
|
func NewQueue[T any]() *Queue[T] {
|
|
return &Queue[T]{}
|
|
}
|
|
|
|
func (q *Queue[T]) Push(item T) {
|
|
q.Buffer = append(q.Buffer, item)
|
|
}
|
|
|
|
// Get returns a single item from a queue. If queue is empty -- it will return io.EOF
|
|
func (q *Queue[T]) Get() (T, error) {
|
|
if len(q.Buffer) == 0 {
|
|
var out T
|
|
return out, io.EOF
|
|
}
|
|
item := q.Buffer[0]
|
|
q.Buffer = q.Buffer[1:]
|
|
return item, nil
|
|
}
|
|
|
|
func (q *Queue[T]) Len() int {
|
|
return len(q.Buffer)
|
|
}
|
|
|
|
// QueueSync is a Queue but for multi thread usage
|
|
type QueueSync[T any] struct {
|
|
IQueue[T]
|
|
Buffer []T
|
|
Mu *sync.Mutex
|
|
NonEmptyCond *sync.Cond
|
|
}
|
|
|
|
// NewQueueSync creates a new QueueSync instance
|
|
func NewQueueSync[T any]() *QueueSync[T] {
|
|
return &QueueSync[T]{
|
|
Mu: &sync.Mutex{},
|
|
NonEmptyCond: sync.NewCond(&sync.RWMutex{}),
|
|
}
|
|
}
|
|
|
|
func (q *QueueSync[T]) Push(item T) {
|
|
q.Mu.Lock()
|
|
q.Buffer = append(q.Buffer, item)
|
|
q.NonEmptyCond.Signal()
|
|
q.Mu.Unlock()
|
|
}
|
|
|
|
func (q *QueueSync[T]) Get() T {
|
|
q.Mu.Lock()
|
|
if len(q.Buffer) < 1 {
|
|
q.NonEmptyCond.Wait()
|
|
}
|
|
item := q.Buffer[0]
|
|
q.Buffer = q.Buffer[1:]
|
|
q.Mu.Unlock()
|
|
return item
|
|
}
|
|
|
|
func (q *QueueSync[T]) Len() int {
|
|
q.Mu.Lock()
|
|
defer q.Mu.Lock()
|
|
return len(q.Buffer)
|
|
}
|