github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/miner/agent.go (about) 1 package miner 2 3 import ( 4 "sync" 5 6 "sync/atomic" 7 8 "github.com/sixexorg/magnetic-ring/consense/poa" 9 "github.com/sixexorg/magnetic-ring/log" 10 ) 11 12 type CpuAgent struct { 13 mu sync.Mutex 14 15 workCh chan *Work 16 stop chan struct{} 17 quitCurrentOp chan struct{} 18 returnCh chan<- *Result 19 20 poaIns *poa.Clique 21 isMining int32 22 } 23 24 func NewCpuAgent(poaIns *poa.Clique) *CpuAgent { 25 miner := &CpuAgent{ 26 poaIns: poaIns, 27 stop: make(chan struct{}, 1), 28 workCh: make(chan *Work, 1), 29 } 30 return miner 31 } 32 33 func (self *CpuAgent) Work() chan<- *Work { return self.workCh } 34 func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch } 35 36 func (self *CpuAgent) Stop() { 37 if !atomic.CompareAndSwapInt32(&self.isMining, 1, 0) { 38 return // agent already stopped 39 } 40 self.stop <- struct{}{} 41 done: 42 // Empty work channel 43 for { 44 select { 45 case <-self.workCh: 46 default: 47 break done 48 } 49 } 50 } 51 52 func (self *CpuAgent) Start() { 53 if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) { 54 return // agent already started 55 } 56 go self.update() 57 } 58 59 func (self *CpuAgent) update() { 60 out: 61 for { 62 select { 63 case work := <-self.workCh: 64 self.mu.Lock() 65 if self.quitCurrentOp != nil { 66 close(self.quitCurrentOp) 67 } 68 self.quitCurrentOp = make(chan struct{}) 69 go self.mine(work, self.quitCurrentOp) // 挖矿计算 70 self.mu.Unlock() 71 case <-self.stop: 72 self.mu.Lock() 73 if self.quitCurrentOp != nil { 74 close(self.quitCurrentOp) 75 self.quitCurrentOp = nil 76 } 77 self.mu.Unlock() 78 break out 79 } 80 } 81 } 82 83 func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) { 84 if result, err := self.poaIns.Seal(work.Block, stop); result != nil { 85 log.Info("Successfully sealed new block", "number", result.Header.Height, "hash", result.Hash()) 86 self.returnCh <- &Result{work, result} 87 } else { 88 if err != nil { 89 log.Warn("Block sealing failed", "err", err) 90 } 91 self.returnCh <- nil 92 } 93 }