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