github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/miner/agent.go (about)

     1  package miner
     2  
     3  import (
     4  	"sync"
     5  
     6  	"sync/atomic"
     7  
     8  	"github.com/neatlab/neatio/chain/consensus"
     9  	ntcTypes "github.com/neatlab/neatio/chain/consensus/neatcon/types"
    10  	"github.com/neatlab/neatio/chain/core/types"
    11  	"github.com/neatlab/neatio/chain/log"
    12  )
    13  
    14  type CpuAgent struct {
    15  	mu sync.Mutex
    16  
    17  	workCh        chan *Work
    18  	stop          chan struct{}
    19  	quitCurrentOp chan struct{}
    20  	returnCh      chan<- *Result
    21  
    22  	chain  consensus.ChainReader
    23  	engine consensus.Engine
    24  
    25  	isMining int32
    26  
    27  	logger log.Logger
    28  }
    29  
    30  func NewCpuAgent(chain consensus.ChainReader, engine consensus.Engine, logger log.Logger) *CpuAgent {
    31  	miner := &CpuAgent{
    32  		chain:  chain,
    33  		engine: engine,
    34  		stop:   make(chan struct{}, 1),
    35  		workCh: make(chan *Work, 1),
    36  		logger: logger,
    37  	}
    38  	return miner
    39  }
    40  
    41  func (self *CpuAgent) Work() chan<- *Work            { return self.workCh }
    42  func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch }
    43  
    44  func (self *CpuAgent) Stop() {
    45  	if !atomic.CompareAndSwapInt32(&self.isMining, 1, 0) {
    46  		return
    47  	}
    48  	self.stop <- struct{}{}
    49  done:
    50  
    51  	for {
    52  		select {
    53  		case <-self.workCh:
    54  		default:
    55  			break done
    56  		}
    57  	}
    58  }
    59  
    60  func (self *CpuAgent) Start() {
    61  	if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) {
    62  		return
    63  	}
    64  	go self.update()
    65  }
    66  
    67  func (self *CpuAgent) update() {
    68  out:
    69  	for {
    70  		select {
    71  		case work := <-self.workCh:
    72  			self.mu.Lock()
    73  			if self.quitCurrentOp != nil {
    74  				close(self.quitCurrentOp)
    75  			}
    76  			self.quitCurrentOp = make(chan struct{})
    77  			go self.mine(work, self.quitCurrentOp)
    78  			self.mu.Unlock()
    79  		case <-self.stop:
    80  			self.mu.Lock()
    81  			if self.quitCurrentOp != nil {
    82  				close(self.quitCurrentOp)
    83  				self.quitCurrentOp = nil
    84  			}
    85  			self.mu.Unlock()
    86  			break out
    87  		}
    88  	}
    89  }
    90  
    91  func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) {
    92  	if result, err := self.engine.Seal(self.chain, work.Block, stop); result != nil {
    93  		switch result := result.(type) {
    94  		case *types.Block:
    95  			self.logger.Info("Successfully minted new block.")
    96  			self.returnCh <- &Result{Work: work, Block: result}
    97  		case *ntcTypes.IntermediateBlockResult:
    98  
    99  			self.returnCh <- &Result{Intermediate: result}
   100  		}
   101  
   102  	} else {
   103  		if err != nil {
   104  			self.logger.Warn("Block sealing failed", "err", err)
   105  		}
   106  		// self.logger.Warn("Block sealing aborted")
   107  		self.returnCh <- nil
   108  	}
   109  }