You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			71 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
		
		
			
		
	
	
			71 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
| 
											2 years ago
										 | package goroutine | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"runtime" | ||
|  | 	"sync" | ||
|  | 
 | ||
| 
											2 years ago
										 | 	"app/container/safe/mpsc" | ||
| 
											2 years ago
										 | 	"go.uber.org/atomic" | ||
|  | ) | ||
|  | 
 | ||
|  | /* | ||
|  | 异步有序任务队列 | ||
|  | 当任务队列空闲时自动释放goroutine | ||
|  | */ | ||
|  | 
 | ||
|  | type Task func() | ||
|  | 
 | ||
|  | const ( | ||
|  | 	idle int32 = iota | ||
|  | 	running | ||
|  | ) | ||
|  | 
 | ||
|  | const DefaultGpsched = 128 | ||
|  | 
 | ||
|  | var _workerPool = sync.Pool{New: func() interface{} { return newWorker() }} | ||
|  | 
 | ||
|  | func GetWorker() *GoWorker  { return _workerPool.Get().(*GoWorker) } | ||
|  | func PutWorker(w *GoWorker) { _workerPool.Put(w) } | ||
|  | func newWorker() *GoWorker  { return &GoWorker{queue: mpsc.New[Task](), gosched: DefaultGpsched} } | ||
|  | 
 | ||
|  | type GoWorker struct { | ||
|  | 	queue           *mpsc.Queue[Task] | ||
|  | 	schedulerStatus atomic.Int32 | ||
|  | 	gosched         int | ||
|  | } | ||
|  | 
 | ||
|  | func (w *GoWorker) SetGosched(gosched int) { w.gosched = gosched } | ||
|  | 
 | ||
|  | func (w *GoWorker) Push(fn Task) { | ||
|  | 	w.queue.Push(fn) | ||
|  | 	if w.schedulerStatus.CAS(idle, running) { | ||
|  | 		if err := _pool.Submit(w.schedule); err != nil { | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | func (w *GoWorker) schedule() { | ||
|  | process: | ||
|  | 	Try(w.run, nil) | ||
|  | 	w.schedulerStatus.Store(idle) | ||
|  | 	if !w.queue.Empty() && w.schedulerStatus.CAS(idle, running) { | ||
|  | 		goto process | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | func (w *GoWorker) run() { | ||
|  | 	count := 0 | ||
|  | 	for { | ||
|  | 		if w.gosched > 0 && count > w.gosched { | ||
|  | 			count = 0 | ||
|  | 			runtime.Gosched() | ||
|  | 		} | ||
|  | 
 | ||
|  | 		fn := w.queue.Pop() | ||
|  | 		if fn == nil { | ||
|  | 			return | ||
|  | 		} | ||
|  | 		fn() | ||
|  | 	} | ||
|  | } |