First implementation
This commit is contained in:
101
vendor/periph.io/x/periph/periph_parallel.go
generated
vendored
Normal file
101
vendor/periph.io/x/periph/periph_parallel.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2018 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This file contains the parallelized driver loading logic. It is meant to be
|
||||
// load the drivers as fast as possible by parallelising work.
|
||||
|
||||
// +build !tinygo
|
||||
|
||||
package periph
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func initImpl() (*State, error) {
|
||||
state = &State{}
|
||||
// At this point, byName is guaranteed to be immutable.
|
||||
cD := make(chan Driver)
|
||||
cS := make(chan DriverFailure)
|
||||
cE := make(chan DriverFailure)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for d := range cD {
|
||||
state.Loaded = insertDriver(state.Loaded, d)
|
||||
}
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for f := range cS {
|
||||
state.Skipped = insertDriverFailure(state.Skipped, f)
|
||||
}
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for f := range cE {
|
||||
state.Failed = insertDriverFailure(state.Failed, f)
|
||||
}
|
||||
}()
|
||||
|
||||
stages, err := explodeStages()
|
||||
if err != nil {
|
||||
return state, err
|
||||
}
|
||||
loaded := make(map[string]struct{}, len(byName))
|
||||
for _, s := range stages {
|
||||
s.loadParallel(loaded, cD, cS, cE)
|
||||
}
|
||||
close(cD)
|
||||
close(cS)
|
||||
close(cE)
|
||||
wg.Wait()
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// loadParallel loads all the drivers for this stage in parallel.
|
||||
//
|
||||
// Updates loaded in a safe way.
|
||||
func (s *stage) loadParallel(loaded map[string]struct{}, cD chan<- Driver, cS, cE chan<- DriverFailure) {
|
||||
success := make(chan string)
|
||||
go func() {
|
||||
defer close(success)
|
||||
wg := sync.WaitGroup{}
|
||||
loop:
|
||||
for name, drv := range s.drvs {
|
||||
// Intentionally do not look at After(), only Prerequisites().
|
||||
for _, dep := range drv.Prerequisites() {
|
||||
if _, ok := loaded[dep]; !ok {
|
||||
cS <- DriverFailure{drv, errors.New("dependency not loaded: " + strconv.Quote(dep))}
|
||||
continue loop
|
||||
}
|
||||
}
|
||||
|
||||
// Not skipped driver, attempt loading in a goroutine.
|
||||
wg.Add(1)
|
||||
go func(n string, d Driver) {
|
||||
defer wg.Done()
|
||||
if ok, err := d.Init(); ok {
|
||||
if err == nil {
|
||||
cD <- d
|
||||
success <- n
|
||||
return
|
||||
}
|
||||
cE <- DriverFailure{d, err}
|
||||
} else {
|
||||
cS <- DriverFailure{d, err}
|
||||
}
|
||||
}(name, drv)
|
||||
}
|
||||
wg.Wait()
|
||||
}()
|
||||
for s := range success {
|
||||
loaded[s] = struct{}{}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user