Fixed miner

* Miners could stall because the worker wasn't aware the miner was done
This commit is contained in:
obscuren 2015-03-26 17:45:03 +01:00
parent d0fa0a234d
commit d36501a6e5
3 changed files with 35 additions and 15 deletions

View File

@ -1,12 +1,15 @@
package miner
import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/pow"
)
type CpuMiner struct {
chMu sync.Mutex
c chan *types.Block
quit chan struct{}
quitCurrentOp chan struct{}
@ -43,16 +46,13 @@ func (self *CpuMiner) Start() {
}
func (self *CpuMiner) update() {
justStarted := true
out:
for {
select {
case block := <-self.c:
if justStarted {
justStarted = true
} else {
self.quitCurrentOp <- struct{}{}
}
self.chMu.Lock()
self.quitCurrentOp <- struct{}{}
self.chMu.Unlock()
go self.mine(block)
case <-self.quit:
@ -60,6 +60,7 @@ out:
}
}
close(self.quitCurrentOp)
done:
// Empty channel
for {
@ -75,12 +76,20 @@ done:
func (self *CpuMiner) mine(block *types.Block) {
minerlogger.Debugf("(re)started agent[%d]. mining...\n", self.index)
// Reset the channel
self.chMu.Lock()
self.quitCurrentOp = make(chan struct{}, 1)
self.chMu.Unlock()
// Mine
nonce, mixDigest, _ := self.pow.Search(block, self.quitCurrentOp)
if nonce != 0 {
block.SetNonce(nonce)
block.Header().MixDigest = common.BytesToHash(mixDigest)
self.returnCh <- block
//self.returnCh <- Work{block.Number().Uint64(), nonce, mixDigest, seedHash}
} else {
self.returnCh <- nil
}
}

View File

@ -50,6 +50,7 @@ out:
break out
case work := <-a.workCh:
a.work = work
a.returnCh <- nil
}
}
}

View File

@ -5,6 +5,7 @@ import (
"math/big"
"sort"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
@ -58,13 +59,14 @@ type Agent interface {
}
type worker struct {
mu sync.Mutex
mu sync.Mutex
agents []Agent
recv chan *types.Block
mux *event.TypeMux
quit chan struct{}
pow pow.PoW
atWork int
atWork int64
eth core.Backend
chain *core.ChainManager
@ -107,7 +109,7 @@ func (self *worker) start() {
func (self *worker) stop() {
self.mining = false
self.atWork = 0
atomic.StoreInt64(&self.atWork, 0)
close(self.quit)
}
@ -135,9 +137,6 @@ out:
self.uncleMu.Unlock()
}
if self.atWork == 0 {
self.commitNewWork()
}
case <-self.quit:
// stop all agents
for _, agent := range self.agents {
@ -146,6 +145,11 @@ out:
break out
case <-timer.C:
minerlogger.Infoln("Hash rate:", self.HashRate(), "Khash")
// XXX In case all mined a possible uncle
if atomic.LoadInt64(&self.atWork) == 0 {
self.commitNewWork()
}
}
}
@ -155,6 +159,12 @@ out:
func (self *worker) wait() {
for {
for block := range self.recv {
atomic.AddInt64(&self.atWork, -1)
if block == nil {
continue
}
if err := self.chain.InsertChain(types.Blocks{block}); err == nil {
for _, uncle := range block.Uncles() {
delete(self.possibleUncles, uncle.Hash())
@ -170,7 +180,6 @@ func (self *worker) wait() {
} else {
self.commitNewWork()
}
self.atWork--
}
}
}
@ -182,8 +191,9 @@ func (self *worker) push() {
// push new work to agents
for _, agent := range self.agents {
atomic.AddInt64(&self.atWork, 1)
agent.Work() <- self.current.block.Copy()
self.atWork++
}
}
}