// Copyright 2018 The dexon-consensus Authors // This file is part of the dexon-consensus library. // // The dexon-consensus library is free software: you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // The dexon-consensus library is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser // General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the dexon-consensus library. If not, see // <http://www.gnu.org/licenses/>. package core import ( "fmt" "sync" "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/types" ) type blockConfirmedEvent struct { block *types.Block } type stronglyAckedEvent struct { blockHash common.Hash } type totalOrderingDeliveredEvent struct { blockHashes common.Hashes mode uint32 } type blockDeliveredEvent struct { blockHash common.Hash result *types.FinalizationResult } // nonBlocking implements these interfaces and is a decorator for // them that makes the methods to be non-blocking. // - Application // - Debug // - It also provides nonblockig for blockdb update. type nonBlocking struct { app Application debug Debug eventChan chan interface{} events []interface{} eventsChange *sync.Cond running sync.WaitGroup } func newNonBlocking(app Application, debug Debug) *nonBlocking { nonBlockingModule := &nonBlocking{ app: app, debug: debug, eventChan: make(chan interface{}, 6), events: make([]interface{}, 0, 100), eventsChange: sync.NewCond(&sync.Mutex{}), } go nonBlockingModule.run() return nonBlockingModule } func (nb *nonBlocking) addEvent(event interface{}) { nb.eventsChange.L.Lock() defer nb.eventsChange.L.Unlock() nb.events = append(nb.events, event) nb.eventsChange.Broadcast() } func (nb *nonBlocking) run() { // This go routine consume the first event from events and call the // corresponding methods of Application/Debug/blockdb. for { var event interface{} func() { nb.eventsChange.L.Lock() defer nb.eventsChange.L.Unlock() for len(nb.events) == 0 { nb.eventsChange.Wait() } event = nb.events[0] nb.events = nb.events[1:] nb.running.Add(1) }() switch e := event.(type) { case stronglyAckedEvent: nb.debug.StronglyAcked(e.blockHash) case blockConfirmedEvent: nb.app.BlockConfirmed(*e.block) case totalOrderingDeliveredEvent: nb.debug.TotalOrderingDelivered(e.blockHashes, e.mode) case blockDeliveredEvent: nb.app.BlockDelivered(e.blockHash, *e.result) default: fmt.Printf("Unknown event %v.", e) } nb.running.Done() nb.eventsChange.Broadcast() } } // wait will wait for all event in events finishes. func (nb *nonBlocking) wait() { nb.eventsChange.L.Lock() defer nb.eventsChange.L.Unlock() for len(nb.events) > 0 { nb.eventsChange.Wait() } nb.running.Wait() } // PreparePayload cannot be non-blocking. func (nb *nonBlocking) PreparePayload(position types.Position) ([]byte, error) { return nb.app.PreparePayload(position) } // PrepareWitness cannot be non-blocking. func (nb *nonBlocking) PrepareWitness(height uint64) (types.Witness, error) { return nb.app.PrepareWitness(height) } // VerifyBlock cannot be non-blocking. func (nb *nonBlocking) VerifyBlock(block *types.Block) types.BlockVerifyStatus { return nb.app.VerifyBlock(block) } // BlockConfirmed is called when a block is confirmed and added to lattice. func (nb *nonBlocking) BlockConfirmed(block types.Block) { nb.addEvent(blockConfirmedEvent{&block}) } // StronglyAcked is called when a block is strongly acked. func (nb *nonBlocking) StronglyAcked(blockHash common.Hash) { if nb.debug != nil { nb.addEvent(stronglyAckedEvent{blockHash}) } } // TotalOrderingDelivered is called when the total ordering algorithm deliver // a set of block. func (nb *nonBlocking) TotalOrderingDelivered( blockHashes common.Hashes, mode uint32) { if nb.debug != nil { nb.addEvent(totalOrderingDeliveredEvent{blockHashes, mode}) } } // BlockDelivered is called when a block is add to the compaction chain. func (nb *nonBlocking) BlockDelivered( blockHash common.Hash, result types.FinalizationResult) { nb.addEvent(blockDeliveredEvent{ blockHash: blockHash, result: &result, }) } </option> <option value='branches/2020Q2'>branches/2020Q2</option> <option value='branches/2020Q3'>branches/2020Q3</option> <option value='branches/2020Q4'>branches/2020Q4</option> <option value='branches/2021Q1'>branches/2021Q1</option> <option value='branches/RELEASE_8_4_0'>branches/RELEASE_8_4_0</option> <option value='branches/RELENG_2_1_0'>branches/RELENG_2_1_0</option> <option value='branches/RELENG_2_2'>branches/RELENG_2_2</option> <option value='branches/RELENG_9_1_0'>branches/RELENG_9_1_0</option> <option value='branches/RELENG_9_2_0'>branches/RELENG_9_2_0</option> <option value='dependabot/npm_and_yarn/devel/electron4/files/eslint-utils-1.4.3'>dependabot/npm_and_yarn/devel/electron4/files/eslint-utils-1.4.3</option> <option value='dependabot/npm_and_yarn/devel/electron4/files/lodash-4.17.15'>dependabot/npm_and_yarn/devel/electron4/files/lodash-4.17.15</option> <option value='dependabot/npm_and_yarn/devel/electron4/files/lodash.merge-4.6.2'>dependabot/npm_and_yarn/devel/electron4/files/lodash.merge-4.6.2</option> <option value='dependabot/npm_and_yarn/devel/electron4/files/lodash.template-4.5.0'>dependabot/npm_and_yarn/devel/electron4/files/lodash.template-4.5.0</option> <option value='dependabot/npm_and_yarn/devel/electron4/files/minimist-1.2.2'>dependabot/npm_and_yarn/devel/electron4/files/minimist-1.2.2</option> <option value='dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2' selected='selected'>dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2</option> <option value='main'>main</option> <option value='master'>master</option> <option value='svn_head'>svn_head</option> </select> <input type='submit' value='switch'/></form></td></tr> <tr><td class='sub'>FreeBSD Ports (https://github.com/freebsd/freebsd-ports)</td><td class='sub right'></td></tr></table> <table class='tabs'><tr><td> <a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/about/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>about</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>summary</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/refs/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd'>refs</a><a class='active' href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/mail/emil?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>log</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/tree/mail/emil?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd'>tree</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/commit/mail/emil?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd'>commit</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/diff/mail/emil?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd'>diff</a><a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/stats/mail/emil?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'>stats</a></td><td class='form'><form class='right' method='get' action='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/mail/emil'> <input type='hidden' name='h' value='dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2'/><input type='hidden' name='id' value='ad97efc883eae561d53ed035d785ab01d970e9bd'/><select name='qt'> <option value='grep'>log msg</option> <option value='author'>author</option> <option value='committer'>committer</option> <option value='range'>range</option> </select> <input class='txt' type='search' size='10' name='q' value=''/> <input type='submit' value='search'/> </form> </td></tr></table> <div class='path'>path: <a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd'>root</a>/<a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/mail?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd'>mail</a>/<a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/mail/emil?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd'>emil</a></div><div class='content'><table class='list nowrap'><tr class='nohover'><th></th><th class='left'>Commit message (<a href='/~lantw44/cgit/cgit.cgi/freebsd-ports/log/mail/emil?h=dependabot/npm_and_yarn/devel/electron4/files/mixin-deep-1.3.2&id=ad97efc883eae561d53ed035d785ab01d970e9bd&showmsg=1'>Expand</a>)</th><th class='left'>Author</th><th class='left'>Age</th><th class='left'>Files</th><th class='left'>Lines</th></tr>