github.com/quinndk/ethereum_read@v0.0.0-20181211143958-29c55eec3237/go-ethereum-master_read/miner/agent.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package miner 18 19 import ( 20 "sync" 21 22 "sync/atomic" 23 24 "github.com/ethereum/go-ethereum/consensus" 25 "github.com/ethereum/go-ethereum/log" 26 ) 27 28 type CpuAgent struct { 29 // 同步锁 30 mu sync.Mutex 31 32 // work通道 33 workCh chan *Work 34 // 结构体通道对象 35 stop chan struct{} 36 quitCurrentOp chan struct{} 37 // Result指针通道 38 returnCh chan<- *Result 39 40 // 共识引擎 41 chain consensus.ChainReader 42 engine consensus.Engine 43 44 // 当前agent是否在挖矿 45 isMining int32 // isMining indicates whether the agent is currently mining 46 } 47 48 func NewCpuAgent(chain consensus.ChainReader, engine consensus.Engine) *CpuAgent { 49 miner := &CpuAgent{ 50 chain: chain, 51 engine: engine, 52 stop: make(chan struct{}, 1), 53 workCh: make(chan *Work, 1), 54 } 55 return miner 56 } 57 58 func (self *CpuAgent) Work() chan<- *Work { return self.workCh } 59 func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch } 60 61 func (self *CpuAgent) Stop() { 62 if !atomic.CompareAndSwapInt32(&self.isMining, 1, 0) { 63 return // agent already stopped 64 } 65 self.stop <- struct{}{} 66 done: 67 // Empty work channel 68 for { 69 select { 70 case <-self.workCh: 71 default: 72 break done 73 } 74 } 75 } 76 77 func (self *CpuAgent) Start() { 78 if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) { 79 return // agent already started 80 } 81 go self.update() 82 } 83 84 func (self *CpuAgent) update() { 85 out: 86 for { 87 select { 88 // 检测是否有工作信号进入 89 case work := <-self.workCh: 90 self.mu.Lock() 91 if self.quitCurrentOp != nil { 92 close(self.quitCurrentOp) 93 } 94 self.quitCurrentOp = make(chan struct{}) 95 go self.mine(work, self.quitCurrentOp) 96 self.mu.Unlock() 97 // 监测停止信号 98 case <-self.stop: 99 self.mu.Lock() 100 if self.quitCurrentOp != nil { 101 close(self.quitCurrentOp) 102 self.quitCurrentOp = nil 103 } 104 self.mu.Unlock() 105 break out 106 } 107 } 108 } 109 110 func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) { 111 112 // 通过共识引擎算法来挖矿 113 if result, err := self.engine.Seal(self.chain, work.Block, stop); result != nil { 114 log.Info("Successfully sealed new block", "number", result.Number(), "hash", result.Hash()) 115 self.returnCh <- &Result{work, result} 116 } else { 117 if err != nil { 118 log.Warn("Block sealing failed", "err", err) 119 } 120 self.returnCh <- nil 121 } 122 } 123 124 func (self *CpuAgent) GetHashRate() int64 { 125 if pow, ok := self.engine.(consensus.PoW); ok { 126 return int64(pow.Hashrate()) 127 } 128 return 0 129 }