build: upgrade to go 1.17 and dependencies
This commit is contained in:
215
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg.go
generated
vendored
Normal file
215
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg.go
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// Package driverreg is a registry for all host driver implementation that can
|
||||
// be automatically discovered.
|
||||
package driverreg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"periph.io/x/conn/v3/driver"
|
||||
)
|
||||
|
||||
// DriverFailure is a driver that wasn't loaded, either because it was skipped
|
||||
// or because it failed to load.
|
||||
type DriverFailure struct {
|
||||
D driver.Impl
|
||||
Err error
|
||||
}
|
||||
|
||||
func (d DriverFailure) String() string {
|
||||
out := d.D.String() + ": "
|
||||
if d.Err != nil {
|
||||
out += d.Err.Error()
|
||||
} else {
|
||||
out += "<nil>"
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// State is the state of loaded device drivers.
|
||||
//
|
||||
// Each list is sorted by the driver name.
|
||||
type State struct {
|
||||
Loaded []driver.Impl
|
||||
Skipped []DriverFailure
|
||||
Failed []DriverFailure
|
||||
}
|
||||
|
||||
// Init initialises all the relevant drivers.
|
||||
//
|
||||
// Drivers are started concurrently.
|
||||
//
|
||||
// It is safe to call this function multiple times, the previous state is
|
||||
// returned on later calls.
|
||||
//
|
||||
// Users will want to use host.Init(), which guarantees a baseline of included
|
||||
// host drivers.
|
||||
func Init() (*State, error) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if state != nil {
|
||||
return state, nil
|
||||
}
|
||||
return initImpl()
|
||||
}
|
||||
|
||||
// Register registers a driver to be initialized automatically on Init().
|
||||
//
|
||||
// The d.String() value must be unique across all registered drivers.
|
||||
//
|
||||
// It is an error to call Register() after Init() was called.
|
||||
func Register(d driver.Impl) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if state != nil {
|
||||
return errors.New("periph: can't call Register() after Init()")
|
||||
}
|
||||
|
||||
n := d.String()
|
||||
if _, ok := byName[n]; ok {
|
||||
return errors.New("periph: driver with same name " + strconv.Quote(n) + " was already registered")
|
||||
}
|
||||
byName[n] = d
|
||||
return nil
|
||||
}
|
||||
|
||||
// MustRegister calls Register() and panics if registration fails.
|
||||
//
|
||||
// This is the function to call in a driver's package init() function.
|
||||
func MustRegister(d driver.Impl) {
|
||||
if err := Register(d); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var (
|
||||
// mu guards byName and state.
|
||||
// - byName is only mutated by Register().
|
||||
// - state is only mutated by Init().
|
||||
//
|
||||
// Once Init() is called, Register() refuses registering more drivers, thus
|
||||
// byName is immutable once Init() started.
|
||||
mu sync.Mutex
|
||||
byName = map[string]driver.Impl{}
|
||||
state *State
|
||||
)
|
||||
|
||||
// stage is a set of drivers that can be loaded in parallel.
|
||||
type stage struct {
|
||||
// Subset of byName drivers, for the ones in this stage.
|
||||
drvs map[string]driver.Impl
|
||||
}
|
||||
|
||||
// explodeStages creates one or multiple stages by processing byName.
|
||||
//
|
||||
// It searches if there's any driver than has dependency on another driver and
|
||||
// create stages from this DAG.
|
||||
//
|
||||
// It also verifies that there is not cycle in the DAG.
|
||||
//
|
||||
// When this function starts, allDriver and byName are guaranteed to be
|
||||
// immutable. state must not be touched by this function.
|
||||
func explodeStages() ([]*stage, error) {
|
||||
// First, create the DAG.
|
||||
dag := map[string]map[string]struct{}{}
|
||||
for name, d := range byName {
|
||||
m := map[string]struct{}{}
|
||||
for _, p := range d.Prerequisites() {
|
||||
if _, ok := byName[p]; !ok {
|
||||
return nil, errors.New("periph: unsatisfied dependency " + strconv.Quote(name) + "->" + strconv.Quote(p) + "; it is missing; skipping")
|
||||
}
|
||||
m[p] = struct{}{}
|
||||
}
|
||||
for _, p := range d.After() {
|
||||
// Skip undefined drivers silently, unlike Prerequisites().
|
||||
if _, ok := byName[p]; ok {
|
||||
m[p] = struct{}{}
|
||||
}
|
||||
}
|
||||
dag[name] = m
|
||||
}
|
||||
|
||||
// Create stages.
|
||||
var stages []*stage
|
||||
for len(dag) != 0 {
|
||||
s := &stage{drvs: map[string]driver.Impl{}}
|
||||
for name, deps := range dag {
|
||||
// This driver has no dependency, add it to the current stage.
|
||||
if len(deps) == 0 {
|
||||
s.drvs[name] = byName[name]
|
||||
delete(dag, name)
|
||||
}
|
||||
}
|
||||
if len(s.drvs) == 0 {
|
||||
// Print out the remaining DAG so users can diagnose.
|
||||
// It'd probably be nicer if it were done in Register()?
|
||||
s := make([]string, 0, len(dag))
|
||||
for name, deps := range dag {
|
||||
x := make([]string, 0, len(deps))
|
||||
for d := range deps {
|
||||
x = insertString(x, d)
|
||||
}
|
||||
s = insertString(s, name+": "+strings.Join(x, ", "))
|
||||
}
|
||||
return nil, errors.New("periph: found cycle(s) in drivers dependencies:\n" + strings.Join(s, "\n"))
|
||||
}
|
||||
stages = append(stages, s)
|
||||
|
||||
// Trim the dependencies for the items remaining in the dag.
|
||||
for passed := range s.drvs {
|
||||
for name := range dag {
|
||||
delete(dag[name], passed)
|
||||
}
|
||||
}
|
||||
}
|
||||
return stages, nil
|
||||
}
|
||||
|
||||
func insertDriver(l []driver.Impl, d driver.Impl) []driver.Impl {
|
||||
n := d.String()
|
||||
i := search(len(l), func(i int) bool { return l[i].String() > n })
|
||||
l = append(l, nil)
|
||||
copy(l[i+1:], l[i:])
|
||||
l[i] = d
|
||||
return l
|
||||
}
|
||||
|
||||
func insertDriverFailure(l []DriverFailure, f DriverFailure) []DriverFailure {
|
||||
n := f.String()
|
||||
i := search(len(l), func(i int) bool { return l[i].String() > n })
|
||||
l = append(l, DriverFailure{})
|
||||
copy(l[i+1:], l[i:])
|
||||
l[i] = f
|
||||
return l
|
||||
}
|
||||
|
||||
func insertString(l []string, s string) []string {
|
||||
i := search(len(l), func(i int) bool { return l[i] > s })
|
||||
l = append(l, "")
|
||||
copy(l[i+1:], l[i:])
|
||||
l[i] = s
|
||||
return l
|
||||
}
|
||||
|
||||
// search implements the same algorithm as sort.Search().
|
||||
//
|
||||
// It was extracted to to not depend on sort, which depends on reflect.
|
||||
func search(n int, f func(int) bool) int {
|
||||
lo := 0
|
||||
for hi := n; lo < hi; {
|
||||
if i := int(uint(lo+hi) >> 1); !f(i) {
|
||||
lo = i + 1
|
||||
} else {
|
||||
hi = i
|
||||
}
|
||||
}
|
||||
return lo
|
||||
}
|
103
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_parallel.go
generated
vendored
Normal file
103
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_parallel.go
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
// 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 driverreg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"periph.io/x/conn/v3/driver"
|
||||
)
|
||||
|
||||
func initImpl() (*State, error) {
|
||||
state = &State{}
|
||||
// At this point, byName is guaranteed to be immutable.
|
||||
cD := make(chan driver.Impl)
|
||||
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.Impl, 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.Impl) {
|
||||
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{}{}
|
||||
}
|
||||
}
|
55
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_serial.go
generated
vendored
Normal file
55
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_serial.go
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
// 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 single threaded driver loading code, to be used on
|
||||
// low performance cores.
|
||||
|
||||
// +build tinygo
|
||||
|
||||
package driverreg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func initImpl() (*State, error) {
|
||||
state = &State{}
|
||||
// At this point, byName is guaranteed to be immutable.
|
||||
stages, err := explodeStages()
|
||||
if err != nil {
|
||||
return state, err
|
||||
}
|
||||
loaded := make(map[string]struct{}, len(byName))
|
||||
for _, s := range stages {
|
||||
s.loadSerial(state, loaded)
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// loadSerial loads all the drivers for this stage, one after the other.
|
||||
func (s *stage) loadSerial(state *State, loaded map[string]struct{}) {
|
||||
for name, drv := range s.drvs {
|
||||
// Intentionally do not look at After(), only Prerequisites().
|
||||
for _, dep := range drv.Prerequisites() {
|
||||
if _, ok := loaded[dep]; !ok {
|
||||
state.Skipped = insertDriverFailure(state.Skipped, DriverFailure{drv, errors.New("dependency not loaded: " + strconv.Quote(dep))})
|
||||
goto loop
|
||||
}
|
||||
}
|
||||
|
||||
// Not skipped driver, attempt loading in a goroutine.
|
||||
if ok, err := drv.Init(); ok {
|
||||
if err == nil {
|
||||
state.Loaded = insertDriver(state.Loaded, drv)
|
||||
loaded[name] = struct{}{}
|
||||
} else {
|
||||
state.Failed = insertDriverFailure(state.Failed, DriverFailure{drv, err})
|
||||
}
|
||||
} else {
|
||||
state.Skipped = insertDriverFailure(state.Skipped, DriverFailure{drv, err})
|
||||
}
|
||||
loop:
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user