Files
go-pkg/queue/queue.go
2021-06-29 21:48:49 +08:00

200 lines
3.1 KiB
Go

package queue
import (
"sync"
)
type (
Queue interface {
Len() int
UnsafeLen() int
Push(ele interface{})
Pop() interface{}
Del(i int)
UnsafeDel(i int)
Get(i int) interface{}
UnsafeGet(i int) interface{}
Set(index int, v interface{})
UnsafeSet(index int, v interface{})
Range(func(i int, v interface{}))
UnsafeRange(func(i int, v interface{}))
Index(data interface{}) (ok bool, i int)
UnsafeIndex(data interface{}) (ok bool, i int)
}
queue struct {
mu *sync.RWMutex
t ListType
count int
data []interface{}
}
ListType int
)
const (
ListTypeQueue ListType = iota + 1
ListTypeStack
)
var _ Queue = &queue{}
func NewQueue(t ListType, defaultCap int) Queue {
switch t {
case ListTypeStack:
case ListTypeQueue:
default:
panic("unknown list type")
}
q := &queue{
mu: &sync.RWMutex{},
count: 0,
t: t,
data: make([]interface{}, 0, defaultCap),
}
return q
}
func (q *queue) init() {
q.count = 0
q.data = make([]interface{}, 0)
}
func (q *queue) checkLen(i int) {
if q.count-1 < i {
panic("out of range")
}
}
func (q *queue) Len() int {
q.mu.RLock()
defer q.mu.RUnlock()
return q.count
}
func (q *queue) UnsafeLen() int {
return q.count
}
//add
func (q *queue) Push(ele interface{}) {
q.mu.Lock()
defer q.mu.Unlock()
q.count++
q.data = append(q.data, ele)
}
//get&remove
func (q *queue) Pop() interface{} {
var data interface{}
q.mu.Lock()
defer q.mu.Unlock()
if q.count == 0 {
return nil
}
switch q.t {
case ListTypeQueue:
data = q.data[0]
q.data = q.data[1:]
case ListTypeStack:
data = q.data[q.count-1]
q.data = q.data[:q.count-1]
}
q.count--
return data
}
//update
func (q *queue) Set(i int, v interface{}) {
q.mu.Lock()
defer q.mu.Unlock()
q.checkLen(i)
q.data[i] = v
}
func (q *queue) UnsafeSet(i int, v interface{}) {
q.checkLen(i)
q.data[i] = v
}
//del
func (q *queue) Del(i int) {
q.mu.Lock()
defer q.mu.Unlock()
q.checkLen(i)
q.data = append(q.data[:i], q.data[i+1:]...)
q.count--
}
func (q *queue) UnsafeDel(i int) {
q.checkLen(i)
q.data = append(q.data[:i], q.data[i+1:]...)
q.count--
}
//Get
func (q *queue) Get(i int) interface{} {
q.mu.RLock()
defer q.mu.RUnlock()
q.checkLen(i)
d := q.data[i]
return d
}
func (q *queue) UnsafeGet(i int) interface{} {
q.checkLen(i)
d := q.data[i]
return d
}
//safe range
func (q *queue) Range(f func(i int, v interface{})) {
q.mu.Lock()
defer q.mu.Unlock()
switch q.t {
case ListTypeQueue:
for i, v := range q.data {
f(i, v)
}
case ListTypeStack:
for i := q.count - 1; i >= 0; i-- {
f(i, q.data[i])
}
}
}
//unsafe range
func (q *queue) UnsafeRange(f func(i int, v interface{})) {
switch q.t {
case ListTypeQueue:
for i, v := range q.data {
f(i, v)
}
case ListTypeStack:
for i := q.count - 1; i >= 0; i-- {
f(i, q.data[i])
}
}
}
func (q *queue) Index(data interface{}) (bool, int) {
q.mu.RLock()
defer q.mu.RUnlock()
for i, v := range q.data {
if v == data {
return true, i
}
}
return false, 0
}
func (q *queue) UnsafeIndex(data interface{}) (bool, int) {
for i, v := range q.data {
if v == data {
return true, i
}
}
return false, 0
}