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  }