mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-31 07:01:20 +00:00
116 lines
2.3 KiB
Go
116 lines
2.3 KiB
Go
|
package v2
|
||
|
|
||
|
import "fmt"
|
||
|
|
||
|
type demuxer struct {
|
||
|
eventbus chan Event
|
||
|
scheduler *Routine
|
||
|
processor *Routine
|
||
|
finished chan error
|
||
|
stopped chan struct{}
|
||
|
}
|
||
|
|
||
|
func newDemuxer(scheduler *Routine, processor *Routine) *demuxer {
|
||
|
return &demuxer{
|
||
|
eventbus: make(chan Event, 10),
|
||
|
scheduler: scheduler,
|
||
|
processor: processor,
|
||
|
stopped: make(chan struct{}, 1),
|
||
|
finished: make(chan error, 1),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// What should the termination clause be?
|
||
|
// Is any of the subroutines finishe, the demuxer finishes
|
||
|
func (dm *demuxer) run() {
|
||
|
fmt.Printf("demuxer: run\n")
|
||
|
for {
|
||
|
select {
|
||
|
case event, ok := <-dm.eventbus:
|
||
|
if !ok {
|
||
|
fmt.Printf("demuxer: stopping\n")
|
||
|
dm.stopped <- struct{}{}
|
||
|
return
|
||
|
}
|
||
|
oEvents, err := dm.handle(event)
|
||
|
if err != nil {
|
||
|
// TODO Termination time
|
||
|
return
|
||
|
}
|
||
|
for _, event := range oEvents {
|
||
|
dm.eventbus <- event
|
||
|
}
|
||
|
case event, ok := <-dm.scheduler.output:
|
||
|
if !ok {
|
||
|
fmt.Printf("demuxer: scheduler output closed\n")
|
||
|
continue
|
||
|
}
|
||
|
oEvents, err := dm.handle(event)
|
||
|
if err != nil {
|
||
|
// TODO tTermination time
|
||
|
return
|
||
|
}
|
||
|
for _, event := range oEvents {
|
||
|
dm.eventbus <- event
|
||
|
}
|
||
|
case event, ok := <-dm.processor.output:
|
||
|
if !ok {
|
||
|
fmt.Printf("demuxer: processor output closed\n")
|
||
|
continue
|
||
|
}
|
||
|
oEvents, err := dm.handle(event)
|
||
|
if err != nil {
|
||
|
// TODO tTermination time
|
||
|
return
|
||
|
}
|
||
|
for _, event := range oEvents {
|
||
|
dm.eventbus <- event
|
||
|
}
|
||
|
case err := <-dm.scheduler.finished:
|
||
|
dm.finished <- err
|
||
|
case err := <-dm.processor.finished:
|
||
|
dm.finished <- err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (dm *demuxer) handle(event Event) (Events, error) {
|
||
|
received := dm.scheduler.send(event)
|
||
|
if !received {
|
||
|
return Events{scFull{}}, nil // backpressure
|
||
|
}
|
||
|
|
||
|
received = dm.processor.send(event)
|
||
|
if !received {
|
||
|
return Events{pcFull{}}, nil // backpressure
|
||
|
}
|
||
|
|
||
|
return Events{}, nil
|
||
|
}
|
||
|
|
||
|
func (dm *demuxer) send(event Event) bool {
|
||
|
fmt.Printf("demuxer send\n")
|
||
|
select {
|
||
|
case dm.eventbus <- event:
|
||
|
return true
|
||
|
default:
|
||
|
fmt.Printf("demuxer channel was full\n")
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (dm *demuxer) stop() {
|
||
|
fmt.Printf("demuxer stop\n")
|
||
|
close(dm.eventbus)
|
||
|
<-dm.stopped
|
||
|
dm.terminate(fmt.Errorf("stopped"))
|
||
|
}
|
||
|
|
||
|
func (dm *demuxer) terminate(reason error) {
|
||
|
dm.finished <- reason
|
||
|
}
|
||
|
|
||
|
func (dm *demuxer) wait() error {
|
||
|
return <-dm.finished
|
||
|
}
|