77 lines
1.1 KiB
Go
77 lines
1.1 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"container/list"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/474420502/focus/compare"
|
||
|
pqueuekey "github.com/474420502/focus/priority_queuekey"
|
||
|
)
|
||
|
|
||
|
type Task struct {
|
||
|
Value int
|
||
|
}
|
||
|
|
||
|
type Queue struct {
|
||
|
lock sync.Mutex
|
||
|
count uint64
|
||
|
|
||
|
waitChans *list.List
|
||
|
|
||
|
queue *pqueuekey.PriorityQueue
|
||
|
}
|
||
|
|
||
|
func NewQueue() *Queue {
|
||
|
return &Queue{
|
||
|
waitChans: list.New(),
|
||
|
queue: pqueuekey.New(compare.UInt64),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (q *Queue) Push(task *Task) {
|
||
|
q.lock.Lock()
|
||
|
defer q.lock.Unlock()
|
||
|
|
||
|
if q.waitChans.Len() != 0 {
|
||
|
element := q.waitChans.Front()
|
||
|
ctask := element.Value.(chan *Task)
|
||
|
ctask <- task
|
||
|
q.waitChans.Remove(element)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
q.count++
|
||
|
q.queue.Push(q.count, task)
|
||
|
}
|
||
|
|
||
|
func (q *Queue) Pop() (task *Task) {
|
||
|
q.lock.Lock()
|
||
|
defer q.lock.Unlock()
|
||
|
q.count++
|
||
|
|
||
|
if itask, ok := q.queue.Pop(); ok {
|
||
|
return itask.(*Task)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (q *Queue) popBlock(task chan *Task) {
|
||
|
q.lock.Lock()
|
||
|
defer q.lock.Unlock()
|
||
|
|
||
|
if q.queue.Size() != 0 {
|
||
|
itask, _ := q.queue.Pop()
|
||
|
go func() { task <- itask.(*Task) }()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
q.waitChans.PushBack(task)
|
||
|
}
|
||
|
|
||
|
func (q *Queue) PopBlock() *Task {
|
||
|
task := make(chan *Task)
|
||
|
q.popBlock(task)
|
||
|
return (<-task)
|
||
|
}
|