github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/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 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/logger" 24 "github.com/ethereum/go-ethereum/logger/glog" 25 "github.com/ethereum/go-ethereum/pow" 26 ) 27 28 type CpuAgent struct { 29 mu sync.Mutex 30 31 workCh chan *Work 32 quit chan struct{} 33 quitCurrentOp chan struct{} 34 returnCh chan<- *Result 35 36 index int 37 pow pow.PoW 38 } 39 40 func NewCpuAgent(index int, pow pow.PoW) *CpuAgent { 41 miner := &CpuAgent{ 42 pow: pow, 43 index: index, 44 } 45 46 return miner 47 } 48 49 func (self *CpuAgent) Work() chan<- *Work { return self.workCh } 50 func (self *CpuAgent) Pow() pow.PoW { return self.pow } 51 func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch } 52 53 func (self *CpuAgent) Stop() { 54 self.mu.Lock() 55 defer self.mu.Unlock() 56 57 close(self.quit) 58 } 59 60 func (self *CpuAgent) Start() { 61 self.mu.Lock() 62 defer self.mu.Unlock() 63 64 self.quit = make(chan struct{}) 65 // creating current op ch makes sure we're not closing a nil ch 66 // later on 67 self.workCh = make(chan *Work, 1) 68 69 go self.update() 70 } 71 72 func (self *CpuAgent) update() { 73 out: 74 for { 75 select { 76 case work := <-self.workCh: 77 self.mu.Lock() 78 if self.quitCurrentOp != nil { 79 close(self.quitCurrentOp) 80 } 81 self.quitCurrentOp = make(chan struct{}) 82 go self.mine(work, self.quitCurrentOp) 83 self.mu.Unlock() 84 case <-self.quit: 85 self.mu.Lock() 86 if self.quitCurrentOp != nil { 87 close(self.quitCurrentOp) 88 self.quitCurrentOp = nil 89 } 90 self.mu.Unlock() 91 break out 92 } 93 } 94 95 done: 96 // Empty work channel 97 for { 98 select { 99 case <-self.workCh: 100 default: 101 close(self.workCh) 102 103 break done 104 } 105 } 106 } 107 108 func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) { 109 glog.V(logger.Debug).Infof("(re)started agent[%d]. mining...\n", self.index) 110 111 // Mine 112 nonce, mixDigest := self.pow.Search(work.Block, stop) 113 if nonce != 0 { 114 block := work.Block.WithMiningResult(nonce, common.BytesToHash(mixDigest)) 115 self.returnCh <- &Result{work, block} 116 } else { 117 self.returnCh <- nil 118 } 119 } 120 121 func (self *CpuAgent) GetHashRate() int64 { 122 return self.pow.GetHashrate() 123 }