diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc78fda --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +cover.out \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..10a8a6e --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, (0x794E6).toString(36) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ed9a552 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: all help test doc + +all: help + +help: ## Show this help + @scripts/help.sh + +test: ## Test potential bugs and race conditions + @scripts/test.sh + +doc: ## Generate docs + @scripts/doc.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..ce9f85a --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# tik + +[![Documentation](https://godoc.org/github.com/andy2046/tik?status.svg)](http://godoc.org/github.com/andy2046/tik) +[![GitHub issues](https://img.shields.io/github/issues/andy2046/tik.svg)](https://github.com/andy2046/tik/issues) +[![license](https://img.shields.io/github/license/andy2046/tik.svg)](https://github.com/andy2046/tik/LICENSE) +[![Release](https://img.shields.io/github/release/andy2046/tik.svg?label=Release)](https://github.com/andy2046/tik/releases) + +---- + +## hierarchical timing wheel made easy + +simplified version of [timeout](https://github.com/wahern/timeout) in Golang + +for documentation, view the [API reference](./doc.md) diff --git a/bit.go b/bit.go new file mode 100644 index 0000000..23c6c56 --- /dev/null +++ b/bit.go @@ -0,0 +1,29 @@ +package tik + +import "math/bits" + +// ROTR(a, k) is a circular shift to the right of bit string a by k slots. +// ROTR is a right shift, where overflowing bits to the right are added back to the left, instead of zeros. +// ROTR(a, k) = ROTL(a, n−k) +func rotr(a uint64, k int) uint64 { + return bits.RotateLeft64(a, -k) +} + +// ROTL(a, k) is a circular shift to the left of bit string a by k slots. +// ROTL is a left shift, where overflowing bits to the left are added back to the right, instead of zeros. +func rotl(a uint64, k int) uint64 { + return bits.RotateLeft64(a, k) +} + +// ctz input cannot be zero. +func ctz(a uint64) int { + return bits.TrailingZeros64(a) +} + +func clz(a uint64) int { + return bits.LeadingZeros64(a) +} + +func fls(a uint64) int { + return 64 - clz(a) +} diff --git a/doc.md b/doc.md new file mode 100644 index 0000000..0729e6e --- /dev/null +++ b/doc.md @@ -0,0 +1,309 @@ + + +# tik +`import "github.com/andy2046/tik"` + +* [Overview](#pkg-overview) +* [Index](#pkg-index) +* [Subdirectories](#pkg-subdirectories) + +## Overview +Package tik implements Hierarchical Timing Wheels. + + + + +## Index +* [Variables](#pkg-variables) +* [type Callback](#Callback) +* [type Config](#Config) +* [type DefaultTimer](#DefaultTimer) + * [func (dt *DefaultTimer) Now() uint64](#DefaultTimer.Now) + * [func (dt *DefaultTimer) Step() <-chan uint64](#DefaultTimer.Step) + * [func (dt *DefaultTimer) Stop()](#DefaultTimer.Stop) +* [type Option](#Option) +* [type Ticker](#Ticker) + * [func New(options ...Option) *Ticker](#New) + * [func (tk *Ticker) AnyExpired() bool](#Ticker.AnyExpired) + * [func (tk *Ticker) AnyPending() bool](#Ticker.AnyPending) + * [func (tk *Ticker) Cancel(to *Timeout)](#Ticker.Cancel) + * [func (tk *Ticker) Close()](#Ticker.Close) + * [func (tk *Ticker) IsClosed() bool](#Ticker.IsClosed) + * [func (tk *Ticker) Schedule(delay uint64, cb Callback) *Timeout](#Ticker.Schedule) +* [type Timeout](#Timeout) + * [func (to *Timeout) Expired() bool](#Timeout.Expired) + * [func (to *Timeout) Pending() bool](#Timeout.Pending) +* [type Timer](#Timer) + * [func NewTimer(interval uint64) Timer](#NewTimer) + + +#### Package files +[bit.go](/src/github.com/andy2046/tik/bit.go) [ticker.go](/src/github.com/andy2046/tik/ticker.go) [timeout.go](/src/github.com/andy2046/tik/timeout.go) [timer.go](/src/github.com/andy2046/tik/timer.go) + + + +## Variables +``` go +var ( + // DefaultConfig is the default Ticker Config. + DefaultConfig = Config{ + WheelBitNum: 6, + WheelNum: 4, + Timer: nil, + } +) +``` + + + +## type [Callback](/src/target/timeout.go?s=147:162#L12) +``` go +type Callback func() +``` +Callback function to trigger when timeout expires. + + + + + + + + + + +## type [Config](/src/target/ticker.go?s=1406:1587#L65) +``` go +type Config struct { + // number of value bits mapped in each wheel. + WheelBitNum uint8 + // number of wheels. + WheelNum uint8 + // Timer to progress the timing wheel. + Timer Timer +} +``` +Config used to init Ticker. + + + + + + + + + + +## type [DefaultTimer](/src/target/timer.go?s=352:484#L22) +``` go +type DefaultTimer struct { + // contains filtered or unexported fields +} +``` +DefaultTimer implements Timer interface. + + + + + + + + + + +### func (\*DefaultTimer) [Now](/src/target/timer.go?s=1157:1193#L62) +``` go +func (dt *DefaultTimer) Now() uint64 +``` +Now returns the absolute time when timer started in millisecond. + + + + +### func (\*DefaultTimer) [Step](/src/target/timer.go?s=1263:1307#L67) +``` go +func (dt *DefaultTimer) Step() <-chan uint64 +``` +Step timing wheel by absolute time in millisecond. + + + + +### func (\*DefaultTimer) [Stop](/src/target/timer.go?s=1359:1389#L72) +``` go +func (dt *DefaultTimer) Stop() +``` +Stop the DefaultTimer. + + + + +## type [Option](/src/target/ticker.go?s=1634:1656#L75) +``` go +type Option = func(*Config) +``` +Option applies config to Ticker Config. + + + + + + + + + + +## type [Ticker](/src/target/ticker.go?s=499:1224#L31) +``` go +type Ticker struct { + // contains filtered or unexported fields +} +``` +Ticker progress the timing wheels. + + + + + + + +### func [New](/src/target/ticker.go?s=1832:1867#L88) +``` go +func New(options ...Option) *Ticker +``` +New initiates a new Ticker. + + + + + +### func (\*Ticker) [AnyExpired](/src/target/ticker.go?s=9546:9581#L432) +``` go +func (tk *Ticker) AnyExpired() bool +``` +AnyExpired returns true if expiry queue is not empty, false otherwise. + + + + +### func (\*Ticker) [AnyPending](/src/target/ticker.go?s=9687:9722#L437) +``` go +func (tk *Ticker) AnyPending() bool +``` +AnyPending returns true if there is task in wheels, false otherwise. + + + + +### func (\*Ticker) [Cancel](/src/target/ticker.go?s=3981:4018#L193) +``` go +func (tk *Ticker) Cancel(to *Timeout) +``` +Cancel the Timeout scheduled if it has not yet expired. + + + + +### func (\*Ticker) [Close](/src/target/ticker.go?s=4137:4162#L203) +``` go +func (tk *Ticker) Close() +``` +Close stop processing any task, +whether it is pending or expired. + + + + +### func (\*Ticker) [IsClosed](/src/target/ticker.go?s=4330:4363#L213) +``` go +func (tk *Ticker) IsClosed() bool +``` +IsClosed returns true if closed, false otherwise. + + + + +### func (\*Ticker) [Schedule](/src/target/ticker.go?s=3704:3766#L181) +``` go +func (tk *Ticker) Schedule(delay uint64, cb Callback) *Timeout +``` +Schedule creates a one-shot action that executed after the given delay. +`delay` is the time from now to delay execution, +the time unit of the delay depends on the Timer provided, default is millisecond. +`cb` is the task to execute. +it returns `nil` if Ticker is closed. + + + + +## type [Timeout](/src/target/timeout.go?s=208:509#L15) +``` go +type Timeout struct { + // contains filtered or unexported fields +} +``` +Timeout represents user timeout logic. + + + + + + + + + + +### func (\*Timeout) [Expired](/src/target/timeout.go?s=1035:1068#L56) +``` go +func (to *Timeout) Expired() bool +``` +Expired returns true if timeout is in expired queue, false otherwise. + + + + +### func (\*Timeout) [Pending](/src/target/timeout.go?s=809:842#L48) +``` go +func (to *Timeout) Pending() bool +``` +Pending returns true if timeout is in timing wheel, false otherwise. + + + + +## type [Timer](/src/target/timer.go?s=102:304#L10) +``` go +type Timer interface { + // Now returns the absolute time when timer started. + Now() uint64 + + // Step channel to step timing wheel by absolute time. + Step() <-chan uint64 + + // Stop the timer. + Stop() +} +``` +Timer progress the timing wheel by current time. + + + + + + + +### func [NewTimer](/src/target/timer.go?s=551:587#L32) +``` go +func NewTimer(interval uint64) Timer +``` +NewTimer returns DefaultTimer with interval in millisecond. + + + + + + + + + +- - - +Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..34cf688 --- /dev/null +++ b/go.mod @@ -0,0 +1,9 @@ +module github.com/andy2046/tik + +go 1.12 + +require ( + github.com/andy2046/gopie v0.7.0 + github.com/andy2046/maths v0.1.0 + golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3d4fef1 --- /dev/null +++ b/go.sum @@ -0,0 +1,30 @@ +github.com/andy2046/bitmap v0.2.0/go.mod h1:+standD/cRz4KSf/bp3rqX2EzKx/e5C+p9PynIBP42M= +github.com/andy2046/gopie v0.7.0 h1:e1jBaJE5SqoXI5ViTwXlOrx9munmbW98I4geDWTRdqc= +github.com/andy2046/gopie v0.7.0/go.mod h1:jIV4Gk+h5tqcadWLLoeM/kHw+ZMLl1yeyIJlsr4akxc= +github.com/andy2046/maths v0.1.0 h1:OSw1DCrJ65I1s3+US9hxmW21Mxd+rzb3HvkZpqAknks= +github.com/andy2046/maths v0.1.0/go.mod h1:N31WEDO1GY6pvCXa1dnZDxkPgferKcCsEcrR2hzUe3U= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-redis/redis v6.14.1+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/scripts/doc.sh b/scripts/doc.sh new file mode 100755 index 0000000..45dbbd3 --- /dev/null +++ b/scripts/doc.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -euo pipefail + +godoc2md github.com/andy2046/tik \ + > $GOPATH/src/github.com/andy2046/tik/doc.md diff --git a/scripts/help.sh b/scripts/help.sh new file mode 100755 index 0000000..f6396b5 --- /dev/null +++ b/scripts/help.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +echo 'usage: make [target] ...' +echo +echo 'targets:' +fgrep -h "##" ./Makefile | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//' diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..fe06f80 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail + +go test -count=1 -v -cover -race +go test -bench=. -run=none -benchtime=3s +go fmt +go vet +golint diff --git a/ticker.go b/ticker.go new file mode 100644 index 0000000..9aa6dc9 --- /dev/null +++ b/ticker.go @@ -0,0 +1,456 @@ +// Package tik implements Hierarchical Timing Wheels. +package tik + +import ( + "math" + "runtime" + "sync" + "sync/atomic" + "unsafe" + + list "github.com/andy2046/gopie/pkg/dll" + "github.com/andy2046/gopie/pkg/log" + "github.com/andy2046/maths" + "golang.org/x/sys/cpu" +) + +const ( + cacheLinePadSize = unsafe.Sizeof(cpu.CacheLinePad{}) +) + +var ( + logger = log.NewLogger(func(c *log.Config) error { + c.Level = log.DEBUG + c.Prefix = "\t" + return nil + }) +) + +type ( + // Ticker progress the timing wheels. + Ticker struct { + _ [cacheLinePadSize]byte + closed uint64 + _ [cacheLinePadSize - 8%cacheLinePadSize]byte + + curtime uint64 + wheelLen uint64 // 1< 64 is the largest + // number of slots which can be tracked. + nWheelBit uint8 + + closer chan struct{} + timer Timer + expired *list.List + wheelz []*wheel + once sync.Once + } + + wheel struct { + _ [cacheLinePadSize]byte + pending uint64 + _ [cacheLinePadSize - 8%cacheLinePadSize]byte + slot []*list.List + } + + // Config used to init Ticker. + Config struct { + // number of value bits mapped in each wheel. + WheelBitNum uint8 + // number of wheels. + WheelNum uint8 + // Timer to progress the timing wheel. + Timer Timer + } + + // Option applies config to Ticker Config. + Option = func(*Config) +) + +var ( + // DefaultConfig is the default Ticker Config. + DefaultConfig = Config{ + WheelBitNum: 6, + WheelNum: 4, + Timer: nil, + } +) + +// New initiates a new Ticker. +func New(options ...Option) *Ticker { + tConfig := DefaultConfig + setOption(&tConfig, options...) + + if tConfig.WheelBitNum < 3 || tConfig.WheelBitNum > 6 { + panic("WheelBitNum should be in range [3, 6]") + } + + switch tConfig.WheelNum { + case 2: + case 4: + case 8: + default: + panic("WheelNum should be in set {2, 4, 8}") + } + + if tConfig.Timer == nil { + tConfig.Timer = NewTimer(100) // 100 millisecond interval + } + + tk := &Ticker{} + tk.init(tConfig.WheelBitNum, tConfig.WheelNum, tConfig.Timer) + + return tk +} + +func (tk *Ticker) init(nWheelBit, nWheel uint8, timer Timer) { + tk.nWheel = nWheel + tk.nWheelBit = nWheelBit + tk.wheelLen = 1 << nWheelBit + tk.wheelMax = 1<> iWheelBit) > tk.wheelMax { + pending = math.MaxUint64 + } else { + elapsedTmp := tk.wheelMask & (elapsed >> iWheelBit) + elapsedTmpShift := uint64((1 << elapsedTmp) - 1) + + oslot := tk.wheelMask & (curtimeTK >> iWheelBit) + pending = rotl(elapsedTmpShift, int(oslot)) + + nslot := tk.wheelMask & (curtime >> iWheelBit) + pending |= rotr(rotl(elapsedTmpShift, int(nslot)), int(elapsedTmp)) + pending |= (1 << nslot) + } + + pp := &tk.wheelz[i].pending + for pending&atomic.LoadUint64(pp) != 0 { + islot := ctz(pending & tk.wheelz[i].pending) + l := tk.wheelz[i].slot[islot] + for !l.Empty() { + ee := l.PopLeft() + if e, ok := ee.(*Timeout); ok { + todo.PushRight(e) + } + } + + for l.Empty() { + p := atomic.LoadUint64(pp) + + if casPending(pp, p, p&^(1< curtime { + rem := tk.rem(expires, curtime) + iwheel := tk.wheel(rem) + islot := tk.slot(iwheel, expires) + + to.m.Lock() + to.iwheel, to.islot = iwheel, islot + to.pending = tk.wheelz[iwheel].slot[islot] + to.element = to.pending.PushRight(to) // link to List + to.expires = expires + to.papa = tk + pending := to.pending + to.m.Unlock() + + for !pending.Empty() { + pp := &tk.wheelz[iwheel].pending + p := atomic.LoadUint64(pp) + + if p&(1<> (wheel * tk.nWheelBit)) - i)) +} + +func (tk *Ticker) rem(expires, curtime uint64) uint64 { + return expires - curtime +} + +func (tk *Ticker) getExpired() *Timeout { + if tk.expired.Empty() { + return nil + } + + to := tk.expired.PopLeft().(*Timeout) + to.m.Lock() + to.pending = nil + to.papa = nil + to.element = nil + to.m.Unlock() + return to +} + +/* +// calculate the interval before needing to process any timeouts pending on +// any wheel. +// +// this might return a timeout value sooner than any installed timeout if +// only higher-order wheels have timeouts pending. It only known when to +// process a wheel, not precisely when a timeout is scheduled. +func (tk *Ticker) interval() uint64 { + var timeoutTmp, relmask, pending uint64 + var timeout uint64 = math.MaxUint64 + var curtime = atomic.LoadUint64(&tk.curtime) + + for i := uint8(0); i < tk.nWheel; i++ { + pending = atomic.LoadUint64(&tk.wheelz[i].pending) + if pending != 0 { + iWheelBit := i * tk.nWheelBit + slot := tk.wheelMask & (curtime >> iWheelBit) + j := 1 + if i == 0 { + j = 0 + } + timeoutTmp = uint64(ctz(rotr(pending, int(slot)))+j) << iWheelBit + timeoutTmp -= (relmask & curtime) + + timeout = maths.Uint64Var.Min(timeoutTmp, timeout) + } + + relmask <<= tk.nWheelBit + relmask |= tk.wheelMask + } + + return timeout +} +*/ + +// AnyExpired returns true if expiry queue is not empty, false otherwise. +func (tk *Ticker) AnyExpired() bool { + return !tk.expired.Empty() +} + +// AnyPending returns true if there is task in wheels, false otherwise. +func (tk *Ticker) AnyPending() bool { + var p uint64 + + for _, w := range tk.wheelz { + p |= atomic.LoadUint64(&w.pending) // race + } + + return p != 0 +} + +// setOption takes one or more Option function and applies them in order to Ticker Config. +func setOption(p *Config, options ...func(*Config)) { + for _, opt := range options { + opt(p) + } +} + +func casPending(p *uint64, c, n uint64) bool { + return atomic.CompareAndSwapUint64(p, c, n) +} diff --git a/ticker_test.go b/ticker_test.go new file mode 100644 index 0000000..b5a49a0 --- /dev/null +++ b/ticker_test.go @@ -0,0 +1,228 @@ +package tik + +import ( + "sync" + "testing" + "time" +) + +func TestOneShotRun(t *testing.T) { + tk := New() + var l sync.RWMutex + i := 0 + cb := func() { + l.Lock() + i++ + l.Unlock() + } + + to := tk.Schedule(500, cb) + + if !to.Pending() { + t.Error("it should be pending") + } + + if to.Expired() { + t.Error("it should NOT be expired") + } + + for { + time.Sleep(100 * time.Millisecond) + + if tk.AnyPending() { + continue + } + + if tk.AnyExpired() { + continue + } + + break + } + + l.RLock() + defer l.RUnlock() + + if i != 1 { + t.Error("fail to callback", i) + } +} + +func TestOneShotCancel(t *testing.T) { + tk := New() + i := 0 + cb := func() { + i++ + } + + to := tk.Schedule(500, cb) + + if !to.Pending() { + t.Error("it should be pending") + } + + if to.Expired() { + t.Error("it should NOT be expired") + } + + go func() { + time.Sleep(200 * time.Millisecond) + tk.Cancel(to) + }() + + for { + time.Sleep(100 * time.Millisecond) + + if tk.AnyPending() { + continue + } + + if tk.AnyExpired() { + continue + } + + break + } + + if i != 0 { + t.Error("fail to Cancel", i) + } +} + +func TestCancelAndCheck(t *testing.T) { + tk := New() + i := 0 + cb := func() { + i++ + } + + to := tk.Schedule(500, cb) + + go func() { + for i := 0; i < 10; i++ { + to.Pending() + to.Expired() + } + }() + + go func() { + time.Sleep(100 * time.Millisecond) + tk.Cancel(to) + }() + + for { + time.Sleep(100 * time.Millisecond) + + if tk.AnyPending() { + continue + } + + if tk.AnyExpired() { + continue + } + + break + } + + if i != 0 { + t.Error("fail to Cancel", i) + } +} + +func TestRunAndCancel(t *testing.T) { + var l sync.RWMutex + var to *Timeout + + tk := New() + i := 0 + n := 10 + cb := func() { + l.Lock() + i++ + l.Unlock() + } + + go func() { + for j := 0; j < n; j++ { + to = tk.Schedule(500, cb) + + go func(to *Timeout) { + for i := 0; i < 10; i++ { + to.Pending() + to.Expired() + } + }(to) + + if 0x1&j == 1 { + go func(to *Timeout) { + tk.Cancel(to) + }(to) + } + } + }() + + for { + time.Sleep(100 * time.Millisecond) + + if tk.AnyPending() { + continue + } + + if tk.AnyExpired() { + continue + } + + break + } + + l.RLock() + defer l.RUnlock() + + if i != 5 { + t.Error("fail to run", i) + } +} + +func TestRunPanic(t *testing.T) { + tk := New() + cb := func() { + panic("test") + } + + to := tk.Schedule(100, cb) + + if !to.Pending() { + t.Error("it should be pending") + } + + if to.Expired() { + t.Error("it should NOT be expired") + } + + for { + time.Sleep(100 * time.Millisecond) + + if tk.AnyPending() { + continue + } + + if tk.AnyExpired() { + continue + } + + break + } +} + +func TestClose(t *testing.T) { + tk := New() + cb := func() {} + + tk.Close() + to := tk.Schedule(500, cb) + tk.Cancel(to) + + if to != nil { + t.Error("it should be nil") + } +} diff --git a/timeout.go b/timeout.go new file mode 100644 index 0000000..26fea87 --- /dev/null +++ b/timeout.go @@ -0,0 +1,61 @@ +package tik + +import ( + "math" + "sync" + + list "github.com/andy2046/gopie/pkg/dll" +) + +type ( + // Callback function to trigger when timeout expires. + Callback func() + + // Timeout represents user timeout logic. + Timeout struct { + // absolute expiration time + expires uint64 + // callbk func when expires + callbk Callback + // timeout list if pending on wheel or expiry queue + pending *list.List + // pointer to ticker + papa *Ticker + + element *list.Element + + iwheel uint8 + islot uint8 + + m sync.RWMutex + } +) + +func newTimeout(cb Callback) *Timeout { + to := &Timeout{} + to.init(cb) + return to +} + +// init initialize timeout. +func (to *Timeout) init(cb Callback) { + to.callbk = cb + to.iwheel = math.MaxUint8 + to.islot = math.MaxUint8 +} + +// Pending returns true if timeout is in timing wheel, false otherwise. +func (to *Timeout) Pending() bool { + to.m.RLock() + defer to.m.RUnlock() + + return to.pending != nil && to.papa != nil && to.pending != to.papa.expired +} + +// Expired returns true if timeout is in expired queue, false otherwise. +func (to *Timeout) Expired() bool { + to.m.RLock() + defer to.m.RUnlock() + + return to.pending != nil && to.papa != nil && to.pending == to.papa.expired +} diff --git a/timer.go b/timer.go new file mode 100644 index 0000000..2d7988e --- /dev/null +++ b/timer.go @@ -0,0 +1,76 @@ +package tik + +import ( + "sync" + "time" +) + +type ( + // Timer progress the timing wheel by current time. + Timer interface { + // Now returns the absolute time when timer started. + Now() uint64 + + // Step channel to step timing wheel by absolute time. + Step() <-chan uint64 + + // Stop the timer. + Stop() + } + + // DefaultTimer implements Timer interface. + DefaultTimer struct { + nowTime time.Time + interval uint64 + absolute chan uint64 + closer chan struct{} + once sync.Once + } +) + +// NewTimer returns DefaultTimer with interval in millisecond. +func NewTimer(interval uint64) Timer { + dt := &DefaultTimer{ + nowTime: time.Now(), + interval: interval, + absolute: make(chan uint64), + closer: make(chan struct{}), + } + + go func() { + tick := time.NewTicker(time.Duration(dt.interval) * time.Millisecond) + defer tick.Stop() + + for { + select { + case <-dt.closer: + return + case t := <-tick.C: + select { + // Go>=1.9 uses a monotonic clock for duration + case dt.absolute <- uint64(t.Sub(dt.nowTime) / time.Millisecond): + default: + } + } + } + }() + + return dt +} + +// Now returns the absolute time when timer started in millisecond. +func (dt *DefaultTimer) Now() uint64 { + return 0 +} + +// Step timing wheel by absolute time in millisecond. +func (dt *DefaultTimer) Step() <-chan uint64 { + return dt.absolute +} + +// Stop the DefaultTimer. +func (dt *DefaultTimer) Stop() { + dt.once.Do(func() { + close(dt.closer) + }) +} diff --git a/vendor/github.com/andy2046/gopie/LICENSE b/vendor/github.com/andy2046/gopie/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/vendor/github.com/andy2046/gopie/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/andy2046/gopie/pkg/dll/amr.go b/vendor/github.com/andy2046/gopie/pkg/dll/amr.go new file mode 100644 index 0000000..1e3493a --- /dev/null +++ b/vendor/github.com/andy2046/gopie/pkg/dll/amr.go @@ -0,0 +1,74 @@ +package dll + +import ( + "sync/atomic" + "unsafe" +) + +type ( + atomicMarkableReference struct { + pair *pair + } + + pair struct { + reference *Element + mark bool + } +) + +func newAtomicMarkableReference(initialRef *Element, initialMark bool) *atomicMarkableReference { + return &atomicMarkableReference{ + &pair{ + reference: initialRef, + mark: initialMark, + }, + } +} + +func (amr *atomicMarkableReference) getPair() *pair { + return (*pair)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&amr.pair)))) +} + +func (amr *atomicMarkableReference) getReference() *Element { + p := amr.getPair() + return p.reference +} + +func (amr *atomicMarkableReference) isMarked() bool { + p := amr.getPair() + return p.mark +} + +func (amr *atomicMarkableReference) get() (bool, *Element) { + p := amr.getPair() + return p.mark, p.reference +} + +func (amr *atomicMarkableReference) compareAndSet(expectedReference *Element, + newReference *Element, + expectedMark bool, + newMark bool) bool { + current := amr.getPair() + val := &pair{newReference, newMark} + + return expectedReference == current.reference && + expectedMark == current.mark && + ((newReference == current.reference && + newMark == current.mark) || + amr.casPair(current, val)) +} + +func (amr *atomicMarkableReference) tryMark(expectedReference *Element, newMark bool) bool { + current := amr.getPair() + val := &pair{expectedReference, newMark} + return expectedReference == current.reference && + (newMark == current.mark || + amr.casPair(current, val)) +} + +func (amr *atomicMarkableReference) casPair(cmp *pair, val *pair) bool { + return atomic.CompareAndSwapPointer( + (*unsafe.Pointer)(unsafe.Pointer(&amr.pair)), + unsafe.Pointer(cmp), + unsafe.Pointer(val)) +} diff --git a/vendor/github.com/andy2046/gopie/pkg/dll/dll.go b/vendor/github.com/andy2046/gopie/pkg/dll/dll.go new file mode 100644 index 0000000..8e82c37 --- /dev/null +++ b/vendor/github.com/andy2046/gopie/pkg/dll/dll.go @@ -0,0 +1,426 @@ +// Package dll provides a lock-free implementation of doubly linked list. +package dll + +type ( + // List represents a doubly linked list. + List struct { + head *Element + tail *Element + } + + // Element is an element of a linked list. + Element struct { + // Next and previous pointers in the doubly-linked list of elements. + next, prev *atomicMarkableReference + + // The value stored with this element. + Value interface{} + } +) + +// New returns an initialized list. +func New() *List { return new(List).Init() } + +// Init initializes or clears list l. +func (l *List) Init() *List { + l.head = &Element{ + prev: newAtomicMarkableReference(nil, false), + next: newAtomicMarkableReference(nil, false), + } + l.tail = &Element{ + prev: newAtomicMarkableReference(nil, false), + next: newAtomicMarkableReference(nil, false), + } + + l.head.next.compareAndSet(nil, l.tail, false, false) + l.tail.prev.compareAndSet(nil, l.head, false, false) + + return l +} + +// Empty returns true if list l is empty, false otherwise +func (l *List) Empty() bool { + t := l.head.next.getReference() + h := l.tail.prev.getReference() + + if t == l.tail && h == l.head { + return true + } + + return false +} + +// Remove removes e from l if e is an element of list l. +// It returns the element value e.Value if succeed, nil otherwise +func (l *List) Remove(e *Element) interface{} { + node := e + if node == nil { + return nil + } + + if node == l.tail || node == l.head { + return nil + } + + for { + removed, nodeNext := node.next.get() + if removed { + return nil + } + if node.next.compareAndSet(nodeNext, nodeNext, false, true) { + for { + removed2, nodePrev := node.prev.get() + if removed2 || node.prev.compareAndSet(nodePrev, nodePrev, false, true) { + break + } + } + + l.correctPrev(node.prev.getReference(), nodeNext) + return node.Value + } + } +} + +func (l *List) correctPrev(prev, node *Element) *Element { + var lastLink *Element + + for { + removed, link1 := node.prev.get() + if removed { + break + } + removed2, prevNext := prev.next.get() + if removed2 { + if lastLink != nil { + setMark(prev.prev) + lastLink.next.compareAndSet(prev, prevNext, false, false) + prev = lastLink + lastLink = nil + continue + } + prevNext = prev.prev.getReference() + prev = prevNext + continue + } + + if prevNext != node { + lastLink = prev + prev = prevNext + continue + } + + if node.prev.compareAndSet(link1, prev, removed, false) { + if prev.prev.isMarked() { + continue + } + break + } + } + + return prev +} + +func setMark(node *atomicMarkableReference) { + for { + removed, link := node.get() + if removed || node.compareAndSet(link, link, false, true) { + break + } + } +} + +// PopLeft returns the first element of list l or nil if the list is empty. +func (l *List) PopLeft() interface{} { + prev := l.head + + for { + node := prev.next.getReference() + // deque is empty + if node == l.tail { + return nil + } + + removed, nodeNext := node.next.get() + // concurrent pop started to delete this node, help it, then continue + if removed { + helpDelete(node, "help concurrent") + continue + } + + // 1 pop step + if node.next.compareAndSet(nodeNext, nodeNext, false, true) { + // 2, 3 step + helpDelete(node, "1st step") + next := node.next.getReference() + // 4 step + helpInsert(prev, next, "popLeft New") + + return node.Value + } + } +} + +// PopRight returns the last element of list l or nil if the list is empty. +func (l *List) PopRight() interface{} { + next := l.tail + node := next.prev.getReference() + + for { + if !node.next.compareAndSet(next, next, false, false) { + node = helpInsert(node, next, "popRight") + continue + } + + if node == l.head { + return nil + } + + if node.next.compareAndSet(next, next, false, true) { + helpDelete(node, "") + prev := node.prev.getReference() + helpInsert(prev, next, "popRight") + + return node.Value + } + } +} + +// PushLeft inserts a new element e with value v at the front of list l and returns e. +func (l *List) PushLeft(v interface{}) *Element { + node := &Element{Value: v} + prev := l.head + next := prev.next.getReference() + + for { + if !prev.next.compareAndSet(next, next, false, false) { + next = prev.next.getReference() + continue + } + + node.prev = newAtomicMarkableReference(prev, false) + node.next = newAtomicMarkableReference(next, false) + + if prev.next.compareAndSet(next, node, false, false) { + break + } + } + + pushCommon(node, next) + + return node +} + +// PushRight inserts a new element e with value v at the back of list l and returns e. +func (l *List) PushRight(v interface{}) *Element { + node := &Element{Value: v} + next := l.tail + prev := next.prev.getReference() + + for { + if !prev.next.compareAndSet(next, next, false, false) { + // concurrent push inserted -> get new prev + prev = helpInsert(prev, next, "concurrentPushRight") + continue + } + + // 0 push step + node.prev = newAtomicMarkableReference(prev, false) + node.next = newAtomicMarkableReference(next, false) + // 1 push step + if prev.next.compareAndSet(next, node, false, false) { + break + } + } + + // 2 push step + pushCommon(node, next) + + return node +} + +func pushCommon(node, next *Element) { + for { + link1 := next.prev + if link1.isMarked() || !node.next.compareAndSet(next, next, false, false) { + break + } + + if next.prev.compareAndSet(link1.getReference(), node, false, false) { + if node.prev.isMarked() { + helpInsert(node, next, "pushCommon") + } + break + } + } +} + +// Next returns the next list element or nil. +func (l *List) Next(node *Element) *Element { + for node != l.tail { + if node == nil { + break + } + + next := node.next.getReference() + if next == nil { + break + } + + removed, nextNext := next.next.get() + if removed { + // The next pointer of the node behind me has the deleted mark set + removed2, nodeNext := node.next.get() + if !removed2 || nodeNext != next { + setMark(next.prev) + node.next.compareAndSet(next, nextNext, false, false) // next removed == false? + continue + } + } + + node = next + + if !removed { + return next + } + } + + return nil +} + +// Prev returns the previous list element or nil. +func (l *List) Prev(node *Element) *Element { + for node != l.head { + if node == nil { + break + } + + prev := node.prev.getReference() + if prev == nil { + break + } + + prevNext := prev.next.getReference() + removed := node.next.isMarked() + + if prevNext == node && !removed { + return prev + } else if removed { + node = l.Next(node) + } else { + prev = l.correctPrev(prev, node) + } + } + + return nil +} + +/** + * Correct node.prev to the closest previous node + * helpInsert is very weak - does not reset node.prev to the actual prev.next + * but just tries to set node.prev to the given suggestion of a prev node + * (for 2 push step, 4 pop step) + */ +func helpInsert(prev *Element, node *Element, method string) *Element { + // last = is the last node : last.next == prev and it is not marked as removed + var last, nodePrev *Element + + for { + removed, prevNext := prev.next.get() + + if removed { + if last != nil { + markPrev(prev) + next2 := prev.next.getReference() + last.next.compareAndSet(prev, next2, false, false) + prev = last + last = nil + } else { + prevNext = prev.prev.getReference() + prev = prevNext + } + continue + } + + removed, nodePrev = node.prev.get() + if removed { + break + } + + // prev is not the previous node of node + if prevNext != node { + last = prev + prev = prevNext + continue + } + + if nodePrev == prev { + break + } + + if prev.next.getReference() == node && node.prev.compareAndSet(nodePrev, prev, false, false) { + if prev.prev.isMarked() { + continue + } + break + } + } + + return prev +} + +// 2 and 3 pop steps +func helpDelete(node *Element, place string) { + markPrev(node) + + prev := node.prev.getReference() + next := node.next.getReference() + var last *Element + + for { + if prev == next { + break + } + + if next.next.isMarked() { + markPrev(next) + next = next.next.getReference() + continue + } + + removed, prevNext := prev.next.get() + if removed { + if last != nil { + markPrev(prev) + next2 := prev.next.getReference() + last.next.compareAndSet(prev, next2, false, false) + prev = last + last = nil + } else { + prevNext = prev.prev.getReference() + prev = prevNext + // assert(prev != nil) + } + continue + } + + if prevNext != node { + last = prev + prev = prevNext + continue + } + + if prev.next.compareAndSet(node, next, false, false) { + break + } + } +} + +func markPrev(node *Element) { + for { + link1 := node.prev + if link1.isMarked() || + node.prev.compareAndSet(link1.getReference(), link1.getReference(), false, true) { + break + } + } +} diff --git a/vendor/github.com/andy2046/gopie/pkg/log/log.go b/vendor/github.com/andy2046/gopie/pkg/log/log.go new file mode 100644 index 0000000..cbb3bc9 --- /dev/null +++ b/vendor/github.com/andy2046/gopie/pkg/log/log.go @@ -0,0 +1,178 @@ +// Package log implements a minimalistic Logger interface. +package log + +import ( + "io" + "log" + "os" + "sync" +) + +type ( + // Level defines Logging level. + Level int + + // Logger is the Logging interface. + Logger interface { + Debug(v ...interface{}) + Info(v ...interface{}) + Warn(v ...interface{}) + Error(v ...interface{}) + Debugf(format string, v ...interface{}) + Infof(format string, v ...interface{}) + Warnf(format string, v ...interface{}) + Errorf(format string, v ...interface{}) + SetLevel(l Level) + LevelLogger(l Level) *log.Logger + } + + // Config used to init Logger. + Config struct { + Level Level + Prefix string + Flag int + DebugHandler io.Writer + InfoHandler io.Writer + WarnHandler io.Writer + ErrorHandler io.Writer + } + + // Option applies config to Logger Config. + Option = func(*Config) error + + defaultLogger struct { + loggerz map[Level]*log.Logger + config *Config + sync.RWMutex + } +) + +// Logging Levels. +const ( + DEBUG Level = iota + INFO + WARN + ERROR +) + +var ( + // DefaultConfig is the default Logger Config. + DefaultConfig = Config{ + Level: INFO, + Prefix: "", + Flag: log.Ldate | log.Ltime, + DebugHandler: os.Stdout, + InfoHandler: os.Stdout, + WarnHandler: os.Stdout, + ErrorHandler: os.Stderr, + } + + _ Logger = &defaultLogger{} +) + +// NewLogger returns a new Logger. +func NewLogger(options ...Option) Logger { + logConfig := DefaultConfig + setOption(&logConfig, options...) + + return &defaultLogger{ + config: &logConfig, + loggerz: setLoggerz(&logConfig), + } +} + +// SetLevel sets the Logging level. +func (dl *defaultLogger) SetLevel(l Level) { + dl.Lock() + dl.config.Level = l + dl.Unlock() +} + +func (dl *defaultLogger) Debug(v ...interface{}) { + dl.log(DEBUG, v...) +} + +func (dl *defaultLogger) Info(v ...interface{}) { + dl.log(INFO, v...) +} + +func (dl *defaultLogger) Warn(v ...interface{}) { + dl.log(WARN, v...) +} + +func (dl *defaultLogger) Error(v ...interface{}) { + dl.log(ERROR, v...) +} + +func (dl *defaultLogger) Debugf(format string, v ...interface{}) { + dl.logf(DEBUG, format, v...) +} + +func (dl *defaultLogger) Infof(format string, v ...interface{}) { + dl.logf(INFO, format, v...) +} + +func (dl *defaultLogger) Warnf(format string, v ...interface{}) { + dl.logf(WARN, format, v...) +} + +func (dl *defaultLogger) Errorf(format string, v ...interface{}) { + dl.logf(ERROR, format, v...) +} + +func (dl *defaultLogger) LevelLogger(l Level) *log.Logger { + dl.RLock() + defer dl.RUnlock() + return dl.loggerz[l] +} + +func (dl *defaultLogger) log(level Level, v ...interface{}) { + dl.RLock() + defer dl.RUnlock() + if dl.config.Level <= level { + dl.loggerz[level].Println(v...) + } +} + +func (dl *defaultLogger) logf(level Level, format string, v ...interface{}) { + dl.RLock() + defer dl.RUnlock() + if dl.config.Level <= level { + dl.loggerz[level].Printf(format, v...) + } +} + +func setOption(c *Config, options ...func(*Config) error) error { + for _, opt := range options { + if err := opt(c); err != nil { + return err + } + } + return nil +} + +func setLoggerz(logConfig *Config) map[Level]*log.Logger { + loggerz := make(map[Level]*log.Logger) + nonErrorLogger := log.New(os.Stdout, logConfig.Prefix, logConfig.Flag) + errorLogger := log.New(os.Stderr, logConfig.Prefix, logConfig.Flag) + + loggerz[DEBUG] = nonErrorLogger + loggerz[INFO] = nonErrorLogger + loggerz[WARN] = nonErrorLogger + loggerz[ERROR] = errorLogger + + if logConfig.DebugHandler != os.Stdout { + loggerz[DEBUG] = log.New(logConfig.DebugHandler, logConfig.Prefix, logConfig.Flag) + } + if logConfig.InfoHandler != os.Stdout { + loggerz[INFO] = log.New(logConfig.InfoHandler, logConfig.Prefix, logConfig.Flag) + } + if logConfig.WarnHandler != os.Stdout { + loggerz[WARN] = log.New(logConfig.WarnHandler, logConfig.Prefix, logConfig.Flag) + } + if logConfig.ErrorHandler != os.Stderr { + loggerz[ERROR] = log.New(logConfig.ErrorHandler, logConfig.Prefix, logConfig.Flag) + } + + return loggerz +} diff --git a/vendor/github.com/andy2046/maths/LICENSE b/vendor/github.com/andy2046/maths/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/vendor/github.com/andy2046/maths/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/andy2046/maths/Makefile b/vendor/github.com/andy2046/maths/Makefile new file mode 100644 index 0000000..ed9a552 --- /dev/null +++ b/vendor/github.com/andy2046/maths/Makefile @@ -0,0 +1,12 @@ +.PHONY: all help test doc + +all: help + +help: ## Show this help + @scripts/help.sh + +test: ## Test potential bugs and race conditions + @scripts/test.sh + +doc: ## Generate docs + @scripts/doc.sh diff --git a/vendor/github.com/andy2046/maths/README.md b/vendor/github.com/andy2046/maths/README.md new file mode 100644 index 0000000..aafe901 --- /dev/null +++ b/vendor/github.com/andy2046/maths/README.md @@ -0,0 +1,22 @@ +# maths + +## makes `Max` `Min` easier +Go `math` pkg provides `Max` `Min` only for `float64`, this lib adds on for other types. + +[Why does Go not have feature X?](https://golang.org/doc/faq#Why_doesnt_Go_have_feature_X) + +### Install + +``` +go get github.com/andy2046/maths +``` + +### Usage + +```go +func main() { + iSlice := []int{1, 2, 3} + i := IntVar.Max(iSlice...) // 3 + i = IntVar.Min(iSlice...) // 1 +} +``` diff --git a/vendor/github.com/andy2046/maths/docs.md b/vendor/github.com/andy2046/maths/docs.md new file mode 100644 index 0000000..f8b989e --- /dev/null +++ b/vendor/github.com/andy2046/maths/docs.md @@ -0,0 +1,623 @@ + + +# maths +`import "github.com/andy2046/maths"` + +* [Overview](#pkg-overview) +* [Index](#pkg-index) + +## Overview + + + +## Index +* [Variables](#pkg-variables) +* [func Range(end int) []struct{}](#Range) +* [func Ternary(expr bool, trueVal, falseVal interface{}) interface{}](#Ternary) +* [type Byte](#Byte) + * [func (Byte) Max(numerics ...byte) byte](#Byte.Max) + * [func (Byte) Min(numerics ...byte) byte](#Byte.Min) +* [type Float32](#Float32) + * [func (Float32) Max(numerics ...float32) float32](#Float32.Max) + * [func (Float32) Min(numerics ...float32) float32](#Float32.Min) +* [type Float64](#Float64) + * [func (Float64) Max(numerics ...float64) float64](#Float64.Max) + * [func (Float64) Min(numerics ...float64) float64](#Float64.Min) +* [type Int](#Int) + * [func (Int) Max(numerics ...int) int](#Int.Max) + * [func (Int) Min(numerics ...int) int](#Int.Min) +* [type Int16](#Int16) + * [func (Int16) Max(numerics ...int16) int16](#Int16.Max) + * [func (Int16) Min(numerics ...int16) int16](#Int16.Min) +* [type Int32](#Int32) + * [func (Int32) Max(numerics ...int32) int32](#Int32.Max) + * [func (Int32) Min(numerics ...int32) int32](#Int32.Min) +* [type Int64](#Int64) + * [func (Int64) Max(numerics ...int64) int64](#Int64.Max) + * [func (Int64) Min(numerics ...int64) int64](#Int64.Min) +* [type Int8](#Int8) + * [func (Int8) Max(numerics ...int8) int8](#Int8.Max) + * [func (Int8) Min(numerics ...int8) int8](#Int8.Min) +* [type Rune](#Rune) + * [func (Rune) Max(numerics ...rune) rune](#Rune.Max) + * [func (Rune) Min(numerics ...rune) rune](#Rune.Min) +* [type String](#String) + * [func (String) Max(numerics ...string) string](#String.Max) + * [func (String) Min(numerics ...string) string](#String.Min) +* [type Uint](#Uint) + * [func (Uint) Max(numerics ...uint) uint](#Uint.Max) + * [func (Uint) Min(numerics ...uint) uint](#Uint.Min) +* [type Uint16](#Uint16) + * [func (Uint16) Max(numerics ...uint16) uint16](#Uint16.Max) + * [func (Uint16) Min(numerics ...uint16) uint16](#Uint16.Min) +* [type Uint32](#Uint32) + * [func (Uint32) Max(numerics ...uint32) uint32](#Uint32.Max) + * [func (Uint32) Min(numerics ...uint32) uint32](#Uint32.Min) +* [type Uint64](#Uint64) + * [func (Uint64) Max(numerics ...uint64) uint64](#Uint64.Max) + * [func (Uint64) Min(numerics ...uint64) uint64](#Uint64.Min) +* [type Uint8](#Uint8) + * [func (Uint8) Max(numerics ...uint8) uint8](#Uint8.Max) + * [func (Uint8) Min(numerics ...uint8) uint8](#Uint8.Min) + + +#### Package files +[maths.go](/src/github.com/andy2046/maths/maths.go) + + + +## Variables +``` go +var ( + // StringVar represents instance of string. + StringVar = new(String) + // IntVar represents instance of int. + IntVar = new(Int) + // Int8Var represents instance of int8. + Int8Var = new(Int8) + // Int16Var represents instance of int16. + Int16Var = new(Int16) + // Int32Var represents instance of int32. + Int32Var = new(Int32) + // Int64Var represents instance of int64. + Int64Var = new(Int64) + // UintVar represents instance of uint. + UintVar = new(Uint) + // Uint8Var represents instance of uint8. + Uint8Var = new(Uint8) + // Uint16Var represents instance of uint16. + Uint16Var = new(Uint16) + // Uint32Var represents instance of uint32. + Uint32Var = new(Uint32) + // Uint64Var represents instance of uint64. + Uint64Var = new(Uint64) + // ByteVar represents instance of byte. + ByteVar = new(Byte) + // RuneVar represents instance of rune. + RuneVar = new(Rune) + // Float32Var represents instance of float32. + Float32Var = new(Float32) + // Float64Var represents instance of float64. + Float64Var = new(Float64) +) +``` + + +## func [Range](/src/target/maths.go?s=1827:1857#L74) +``` go +func Range(end int) []struct{} +``` +Range creates a range progressing from zero up to, but not including end. + + + +## func [Ternary](/src/target/maths.go?s=8017:8083#L401) +``` go +func Ternary(expr bool, trueVal, falseVal interface{}) interface{} +``` +Ternary for no ternary operation in Go. + + + + +## type [Byte](/src/target/maths.go?s=580:589#L31) +``` go +type Byte byte +``` +Byte represents type byte. + + + + + + + + + + +### func (Byte) [Max](/src/target/maths.go?s=3160:3198#L137) +``` go +func (Byte) Max(numerics ...byte) byte +``` +Max returns the largest in numerics. + + + + +### func (Byte) [Min](/src/target/maths.go?s=3360:3398#L148) +``` go +func (Byte) Min(numerics ...byte) byte +``` +Min returns the smallest in numerics. + + + + +## type [Float32](/src/target/maths.go?s=670:685#L35) +``` go +type Float32 float32 +``` +Float32 represents type float32. + + + + + + + + + + +### func (Float32) [Max](/src/target/maths.go?s=1933:1980#L79) +``` go +func (Float32) Max(numerics ...float32) float32 +``` +Max returns the largest in numerics. + + + + +### func (Float32) [Min](/src/target/maths.go?s=2154:2201#L88) +``` go +func (Float32) Min(numerics ...float32) float32 +``` +Min returns the smallest in numerics. + + + + +## type [Float64](/src/target/maths.go?s=724:739#L37) +``` go +type Float64 float64 +``` +Float64 represents type float64. + + + + + + + + + + +### func (Float64) [Max](/src/target/maths.go?s=2374:2421#L97) +``` go +func (Float64) Max(numerics ...float64) float64 +``` +Max returns the largest in numerics. + + + + +### func (Float64) [Min](/src/target/maths.go?s=2568:2615#L106) +``` go +func (Float64) Min(numerics ...float64) float64 +``` +Min returns the smallest in numerics. + + + + +## type [Int](/src/target/maths.go?s=122:129#L11) +``` go +type Int int +``` +Int represents type int. + + + + + + + + + + +### func (Int) [Max](/src/target/maths.go?s=7210:7245#L357) +``` go +func (Int) Max(numerics ...int) int +``` +Max returns the largest in numerics. + + + + +### func (Int) [Min](/src/target/maths.go?s=7407:7442#L368) +``` go +func (Int) Min(numerics ...int) int +``` +Min returns the smallest in numerics. + + + + +## type [Int16](/src/target/maths.go?s=206:217#L15) +``` go +type Int16 int16 +``` +Int16 represents type int16. + + + + + + + + + + +### func (Int16) [Max](/src/target/maths.go?s=6406:6447#L313) +``` go +func (Int16) Max(numerics ...int16) int16 +``` +Max returns the largest in numerics. + + + + +### func (Int16) [Min](/src/target/maths.go?s=6609:6650#L324) +``` go +func (Int16) Min(numerics ...int16) int16 +``` +Min returns the smallest in numerics. + + + + +## type [Int32](/src/target/maths.go?s=252:263#L17) +``` go +type Int32 int32 +``` +Int32 represents type int32. + + + + + + + + + + +### func (Int32) [Max](/src/target/maths.go?s=6001:6042#L291) +``` go +func (Int32) Max(numerics ...int32) int32 +``` +Max returns the largest in numerics. + + + + +### func (Int32) [Min](/src/target/maths.go?s=6204:6245#L302) +``` go +func (Int32) Min(numerics ...int32) int32 +``` +Min returns the smallest in numerics. + + + + +## type [Int64](/src/target/maths.go?s=298:309#L19) +``` go +type Int64 int64 +``` +Int64 represents type int64. + + + + + + + + + + +### func (Int64) [Max](/src/target/maths.go?s=5596:5637#L269) +``` go +func (Int64) Max(numerics ...int64) int64 +``` +Max returns the largest in numerics. + + + + +### func (Int64) [Min](/src/target/maths.go?s=5799:5840#L280) +``` go +func (Int64) Min(numerics ...int64) int64 +``` +Min returns the smallest in numerics. + + + + +## type [Int8](/src/target/maths.go?s=162:171#L13) +``` go +type Int8 int8 +``` +Int8 represents type int8. + + + + + + + + + + +### func (Int8) [Max](/src/target/maths.go?s=6811:6849#L335) +``` go +func (Int8) Max(numerics ...int8) int8 +``` +Max returns the largest in numerics. + + + + +### func (Int8) [Min](/src/target/maths.go?s=7011:7049#L346) +``` go +func (Int8) Min(numerics ...int8) int8 +``` +Min returns the smallest in numerics. + + + + +## type [Rune](/src/target/maths.go?s=622:631#L33) +``` go +type Rune rune +``` +Rune represents type rune. + + + + + + + + + + +### func (Rune) [Max](/src/target/maths.go?s=2761:2799#L115) +``` go +func (Rune) Max(numerics ...rune) rune +``` +Max returns the largest in numerics. + + + + +### func (Rune) [Min](/src/target/maths.go?s=2961:2999#L126) +``` go +func (Rune) Min(numerics ...rune) rune +``` +Min returns the smallest in numerics. + + + + +## type [String](/src/target/maths.go?s=78:91#L9) +``` go +type String string +``` +String represents type string. + + + + + + + + + + +### func (String) [Max](/src/target/maths.go?s=7603:7647#L379) +``` go +func (String) Max(numerics ...string) string +``` +Max returns the largest in numerics. + + + + +### func (String) [Min](/src/target/maths.go?s=7809:7853#L390) +``` go +func (String) Min(numerics ...string) string +``` +Min returns the smallest in numerics. + + + + +## type [Uint](/src/target/maths.go?s=342:351#L21) +``` go +type Uint uint +``` +Uint represents type uint. + + + + + + + + + + +### func (Uint) [Max](/src/target/maths.go?s=5197:5235#L247) +``` go +func (Uint) Max(numerics ...uint) uint +``` +Max returns the largest in numerics. + + + + +### func (Uint) [Min](/src/target/maths.go?s=5397:5435#L258) +``` go +func (Uint) Min(numerics ...uint) uint +``` +Min returns the smallest in numerics. + + + + +## type [Uint16](/src/target/maths.go?s=434:447#L25) +``` go +type Uint16 uint16 +``` +Uint16 represents type uint16. + + + + + + + + + + +### func (Uint16) [Max](/src/target/maths.go?s=4381:4425#L203) +``` go +func (Uint16) Max(numerics ...uint16) uint16 +``` +Max returns the largest in numerics. + + + + +### func (Uint16) [Min](/src/target/maths.go?s=4587:4631#L214) +``` go +func (Uint16) Min(numerics ...uint16) uint16 +``` +Min returns the smallest in numerics. + + + + +## type [Uint32](/src/target/maths.go?s=484:497#L27) +``` go +type Uint32 uint32 +``` +Uint32 represents type uint32. + + + + + + + + + + +### func (Uint32) [Max](/src/target/maths.go?s=3970:4014#L181) +``` go +func (Uint32) Max(numerics ...uint32) uint32 +``` +Max returns the largest in numerics. + + + + +### func (Uint32) [Min](/src/target/maths.go?s=4176:4220#L192) +``` go +func (Uint32) Min(numerics ...uint32) uint32 +``` +Min returns the smallest in numerics. + + + + +## type [Uint64](/src/target/maths.go?s=534:547#L29) +``` go +type Uint64 uint64 +``` +Uint64 represents type uint64. + + + + + + + + + + +### func (Uint64) [Max](/src/target/maths.go?s=3559:3603#L159) +``` go +func (Uint64) Max(numerics ...uint64) uint64 +``` +Max returns the largest in numerics. + + + + +### func (Uint64) [Min](/src/target/maths.go?s=3765:3809#L170) +``` go +func (Uint64) Min(numerics ...uint64) uint64 +``` +Min returns the smallest in numerics. + + + + +## type [Uint8](/src/target/maths.go?s=386:397#L23) +``` go +type Uint8 uint8 +``` +Uint8 represents type uint8. + + + + + + + + + + +### func (Uint8) [Max](/src/target/maths.go?s=4792:4833#L225) +``` go +func (Uint8) Max(numerics ...uint8) uint8 +``` +Max returns the largest in numerics. + + + + +### func (Uint8) [Min](/src/target/maths.go?s=4995:5036#L236) +``` go +func (Uint8) Min(numerics ...uint8) uint8 +``` +Min returns the smallest in numerics. + + + + + + + + +- - - +Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) diff --git a/vendor/github.com/andy2046/maths/maths.go b/vendor/github.com/andy2046/maths/maths.go new file mode 100644 index 0000000..d0b4579 --- /dev/null +++ b/vendor/github.com/andy2046/maths/maths.go @@ -0,0 +1,406 @@ +package maths + +import ( + "math" +) + +type ( + // String represents type string. + String string + // Int represents type int. + Int int + // Int8 represents type int8. + Int8 int8 + // Int16 represents type int16. + Int16 int16 + // Int32 represents type int32. + Int32 int32 + // Int64 represents type int64. + Int64 int64 + // Uint represents type uint. + Uint uint + // Uint8 represents type uint8. + Uint8 uint8 + // Uint16 represents type uint16. + Uint16 uint16 + // Uint32 represents type uint32. + Uint32 uint32 + // Uint64 represents type uint64. + Uint64 uint64 + // Byte represents type byte. + Byte byte + // Rune represents type rune. + Rune rune + // Float32 represents type float32. + Float32 float32 + // Float64 represents type float64. + Float64 float64 +) + +var ( + // StringVar represents instance of string. + StringVar = new(String) + // IntVar represents instance of int. + IntVar = new(Int) + // Int8Var represents instance of int8. + Int8Var = new(Int8) + // Int16Var represents instance of int16. + Int16Var = new(Int16) + // Int32Var represents instance of int32. + Int32Var = new(Int32) + // Int64Var represents instance of int64. + Int64Var = new(Int64) + // UintVar represents instance of uint. + UintVar = new(Uint) + // Uint8Var represents instance of uint8. + Uint8Var = new(Uint8) + // Uint16Var represents instance of uint16. + Uint16Var = new(Uint16) + // Uint32Var represents instance of uint32. + Uint32Var = new(Uint32) + // Uint64Var represents instance of uint64. + Uint64Var = new(Uint64) + // ByteVar represents instance of byte. + ByteVar = new(Byte) + // RuneVar represents instance of rune. + RuneVar = new(Rune) + // Float32Var represents instance of float32. + Float32Var = new(Float32) + // Float64Var represents instance of float64. + Float64Var = new(Float64) +) + +// Range creates a range progressing from zero up to, but not including end. +func Range(end int) []struct{} { + return make([]struct{}, end) +} + +// Max returns the largest in numerics. +func (Float32) Max(numerics ...float32) float32 { + n := float64(numerics[0]) + for i := 1; i < len(numerics); i++ { + n = math.Max(float64(numerics[i]), n) + } + return float32(n) +} + +// Min returns the smallest in numerics. +func (Float32) Min(numerics ...float32) float32 { + n := float64(numerics[0]) + for i := 1; i < len(numerics); i++ { + n = math.Min(float64(numerics[i]), n) + } + return float32(n) +} + +// Max returns the largest in numerics. +func (Float64) Max(numerics ...float64) float64 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + n = math.Max(numerics[i], n) + } + return n +} + +// Min returns the smallest in numerics. +func (Float64) Min(numerics ...float64) float64 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + n = math.Min(numerics[i], n) + } + return n +} + +// Max returns the largest in numerics. +func (Rune) Max(numerics ...rune) rune { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Rune) Min(numerics ...rune) rune { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Byte) Max(numerics ...byte) byte { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Byte) Min(numerics ...byte) byte { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Uint64) Max(numerics ...uint64) uint64 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Uint64) Min(numerics ...uint64) uint64 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Uint32) Max(numerics ...uint32) uint32 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Uint32) Min(numerics ...uint32) uint32 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Uint16) Max(numerics ...uint16) uint16 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Uint16) Min(numerics ...uint16) uint16 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Uint8) Max(numerics ...uint8) uint8 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Uint8) Min(numerics ...uint8) uint8 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Uint) Max(numerics ...uint) uint { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Uint) Min(numerics ...uint) uint { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Int64) Max(numerics ...int64) int64 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Int64) Min(numerics ...int64) int64 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Int32) Max(numerics ...int32) int32 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Int32) Min(numerics ...int32) int32 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Int16) Max(numerics ...int16) int16 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Int16) Min(numerics ...int16) int16 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Int8) Max(numerics ...int8) int8 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Int8) Min(numerics ...int8) int8 { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (Int) Max(numerics ...int) int { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (Int) Min(numerics ...int) int { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Max returns the largest in numerics. +func (String) Max(numerics ...string) string { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] > n { + n = numerics[i] + } + } + return n +} + +// Min returns the smallest in numerics. +func (String) Min(numerics ...string) string { + n := numerics[0] + for i := 1; i < len(numerics); i++ { + if numerics[i] < n { + n = numerics[i] + } + } + return n +} + +// Ternary for no ternary operation in Go. +func Ternary(expr bool, trueVal, falseVal interface{}) interface{} { + if expr { + return trueVal + } + return falseVal +} diff --git a/vendor/golang.org/x/sys/AUTHORS b/vendor/golang.org/x/sys/AUTHORS new file mode 100644 index 0000000..15167cd --- /dev/null +++ b/vendor/golang.org/x/sys/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/sys/CONTRIBUTORS b/vendor/golang.org/x/sys/CONTRIBUTORS new file mode 100644 index 0000000..1c4577e --- /dev/null +++ b/vendor/golang.org/x/sys/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE new file mode 100644 index 0000000..6a66aea --- /dev/null +++ b/vendor/golang.org/x/sys/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/sys/PATENTS b/vendor/golang.org/x/sys/PATENTS new file mode 100644 index 0000000..7330990 --- /dev/null +++ b/vendor/golang.org/x/sys/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s new file mode 100644 index 0000000..06f84b8 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s @@ -0,0 +1,17 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo + +#include "textflag.h" + +// +// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go +// + +TEXT ·syscall6(SB),NOSPLIT,$0-88 + JMP syscall·syscall6(SB) + +TEXT ·rawSyscall6(SB),NOSPLIT,$0-88 + JMP syscall·rawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/cpu/byteorder.go b/vendor/golang.org/x/sys/cpu/byteorder.go new file mode 100644 index 0000000..ed8da8d --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/byteorder.go @@ -0,0 +1,60 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "runtime" +) + +// byteOrder is a subset of encoding/binary.ByteOrder. +type byteOrder interface { + Uint32([]byte) uint32 + Uint64([]byte) uint64 +} + +type littleEndian struct{} +type bigEndian struct{} + +func (littleEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func (littleEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func (bigEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 +} + +func (bigEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 +} + +// hostByteOrder returns binary.LittleEndian on little-endian machines and +// binary.BigEndian on big-endian machines. +func hostByteOrder() byteOrder { + switch runtime.GOARCH { + case "386", "amd64", "amd64p32", + "arm", "arm64", + "mipsle", "mips64le", "mips64p32le", + "ppc64le", + "riscv", "riscv64": + return littleEndian{} + case "armbe", "arm64be", + "mips", "mips64", "mips64p32", + "ppc", "ppc64", + "s390", "s390x", + "sparc", "sparc64": + return bigEndian{} + } + panic("unknown architecture") +} diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go new file mode 100644 index 0000000..e44deb7 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -0,0 +1,171 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cpu implements processor feature detection for +// various CPU architectures. +package cpu + +// Initialized reports whether the CPU features were initialized. +// +// For some GOOS/GOARCH combinations initialization of the CPU features depends +// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm +// Initialized will report false if reading the file fails. +var Initialized bool + +// CacheLinePad is used to pad structs to avoid false sharing. +type CacheLinePad struct{ _ [cacheLineSize]byte } + +// X86 contains the supported CPU features of the +// current X86/AMD64 platform. If the current platform +// is not X86/AMD64 then all feature flags are false. +// +// X86 is padded to avoid false sharing. Further the HasAVX +// and HasAVX2 are only set if the OS supports XMM and YMM +// registers in addition to the CPUID feature bit being set. +var X86 struct { + _ CacheLinePad + HasAES bool // AES hardware implementation (AES NI) + HasADX bool // Multi-precision add-carry instruction extensions + HasAVX bool // Advanced vector extension + HasAVX2 bool // Advanced vector extension 2 + HasBMI1 bool // Bit manipulation instruction set 1 + HasBMI2 bool // Bit manipulation instruction set 2 + HasERMS bool // Enhanced REP for MOVSB and STOSB + HasFMA bool // Fused-multiply-add instructions + HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. + HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM + HasPOPCNT bool // Hamming weight instruction POPCNT. + HasRDRAND bool // RDRAND instruction (on-chip random number generator) + HasRDSEED bool // RDSEED instruction (on-chip random number generator) + HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) + HasSSE3 bool // Streaming SIMD extension 3 + HasSSSE3 bool // Supplemental streaming SIMD extension 3 + HasSSE41 bool // Streaming SIMD extension 4 and 4.1 + HasSSE42 bool // Streaming SIMD extension 4 and 4.2 + _ CacheLinePad +} + +// ARM64 contains the supported CPU features of the +// current ARMv8(aarch64) platform. If the current platform +// is not arm64 then all feature flags are false. +var ARM64 struct { + _ CacheLinePad + HasFP bool // Floating-point instruction set (always available) + HasASIMD bool // Advanced SIMD (always available) + HasEVTSTRM bool // Event stream support + HasAES bool // AES hardware implementation + HasPMULL bool // Polynomial multiplication instruction set + HasSHA1 bool // SHA1 hardware implementation + HasSHA2 bool // SHA2 hardware implementation + HasCRC32 bool // CRC32 hardware implementation + HasATOMICS bool // Atomic memory operation instruction set + HasFPHP bool // Half precision floating-point instruction set + HasASIMDHP bool // Advanced SIMD half precision instruction set + HasCPUID bool // CPUID identification scheme registers + HasASIMDRDM bool // Rounding double multiply add/subtract instruction set + HasJSCVT bool // Javascript conversion from floating-point to integer + HasFCMA bool // Floating-point multiplication and addition of complex numbers + HasLRCPC bool // Release Consistent processor consistent support + HasDCPOP bool // Persistent memory support + HasSHA3 bool // SHA3 hardware implementation + HasSM3 bool // SM3 hardware implementation + HasSM4 bool // SM4 hardware implementation + HasASIMDDP bool // Advanced SIMD double precision instruction set + HasSHA512 bool // SHA512 hardware implementation + HasSVE bool // Scalable Vector Extensions + HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 + _ CacheLinePad +} + +// ARM contains the supported CPU features of the current ARM (32-bit) platform. +// All feature flags are false if: +// 1. the current platform is not arm, or +// 2. the current operating system is not Linux. +var ARM struct { + _ CacheLinePad + HasSWP bool // SWP instruction support + HasHALF bool // Half-word load and store support + HasTHUMB bool // ARM Thumb instruction set + Has26BIT bool // Address space limited to 26-bits + HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support + HasFPA bool // Floating point arithmetic support + HasVFP bool // Vector floating point support + HasEDSP bool // DSP Extensions support + HasJAVA bool // Java instruction set + HasIWMMXT bool // Intel Wireless MMX technology support + HasCRUNCH bool // MaverickCrunch context switching and handling + HasTHUMBEE bool // Thumb EE instruction set + HasNEON bool // NEON instruction set + HasVFPv3 bool // Vector floating point version 3 support + HasVFPv3D16 bool // Vector floating point version 3 D8-D15 + HasTLS bool // Thread local storage support + HasVFPv4 bool // Vector floating point version 4 support + HasIDIVA bool // Integer divide instruction support in ARM mode + HasIDIVT bool // Integer divide instruction support in Thumb mode + HasVFPD32 bool // Vector floating point version 3 D15-D31 + HasLPAE bool // Large Physical Address Extensions + HasEVTSTRM bool // Event stream support + HasAES bool // AES hardware implementation + HasPMULL bool // Polynomial multiplication instruction set + HasSHA1 bool // SHA1 hardware implementation + HasSHA2 bool // SHA2 hardware implementation + HasCRC32 bool // CRC32 hardware implementation + _ CacheLinePad +} + +// MIPS64X contains the supported CPU features of the current mips64/mips64le +// platforms. If the current platform is not mips64/mips64le or the current +// operating system is not Linux then all feature flags are false. +var MIPS64X struct { + _ CacheLinePad + HasMSA bool // MIPS SIMD architecture + _ CacheLinePad +} + +// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. +// If the current platform is not ppc64/ppc64le then all feature flags are false. +// +// For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, +// since there are no optional categories. There are some exceptions that also +// require kernel support to work (DARN, SCV), so there are feature bits for +// those as well. The minimum processor requirement is POWER8 (ISA 2.07). +// The struct is padded to avoid false sharing. +var PPC64 struct { + _ CacheLinePad + HasDARN bool // Hardware random number generator (requires kernel enablement) + HasSCV bool // Syscall vectored (requires kernel enablement) + IsPOWER8 bool // ISA v2.07 (POWER8) + IsPOWER9 bool // ISA v3.00 (POWER9) + _ CacheLinePad +} + +// S390X contains the supported CPU features of the current IBM Z +// (s390x) platform. If the current platform is not IBM Z then all +// feature flags are false. +// +// S390X is padded to avoid false sharing. Further HasVX is only set +// if the OS supports vector registers in addition to the STFLE +// feature bit being set. +var S390X struct { + _ CacheLinePad + HasZARCH bool // z/Architecture mode is active [mandatory] + HasSTFLE bool // store facility list extended + HasLDISP bool // long (20-bit) displacements + HasEIMM bool // 32-bit immediates + HasDFP bool // decimal floating point + HasETF3EH bool // ETF-3 enhanced + HasMSA bool // message security assist (CPACF) + HasAES bool // KM-AES{128,192,256} functions + HasAESCBC bool // KMC-AES{128,192,256} functions + HasAESCTR bool // KMCTR-AES{128,192,256} functions + HasAESGCM bool // KMA-GCM-AES{128,192,256} functions + HasGHASH bool // KIMD-GHASH function + HasSHA1 bool // K{I,L}MD-SHA-1 functions + HasSHA256 bool // K{I,L}MD-SHA-256 functions + HasSHA512 bool // K{I,L}MD-SHA-512 functions + HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions + HasVX bool // vector facility + HasVXE bool // vector-enhancements facility 1 + _ CacheLinePad +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go b/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go new file mode 100644 index 0000000..be60272 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go @@ -0,0 +1,34 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build aix,ppc64 + +package cpu + +const cacheLineSize = 128 + +const ( + // getsystemcfg constants + _SC_IMPL = 2 + _IMPL_POWER8 = 0x10000 + _IMPL_POWER9 = 0x20000 +) + +func init() { + impl := getsystemcfg(_SC_IMPL) + if impl&_IMPL_POWER8 != 0 { + PPC64.IsPOWER8 = true + } + if impl&_IMPL_POWER9 != 0 { + PPC64.IsPOWER9 = true + } + + Initialized = true +} + +func getsystemcfg(label int) (n uint64) { + r0, _ := callgetsystemcfg(label) + n = uint64(r0) + return +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go new file mode 100644 index 0000000..981af68 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm.go @@ -0,0 +1,40 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 32 + +// HWCAP/HWCAP2 bits. +// These are specific to Linux. +const ( + hwcap_SWP = 1 << 0 + hwcap_HALF = 1 << 1 + hwcap_THUMB = 1 << 2 + hwcap_26BIT = 1 << 3 + hwcap_FAST_MULT = 1 << 4 + hwcap_FPA = 1 << 5 + hwcap_VFP = 1 << 6 + hwcap_EDSP = 1 << 7 + hwcap_JAVA = 1 << 8 + hwcap_IWMMXT = 1 << 9 + hwcap_CRUNCH = 1 << 10 + hwcap_THUMBEE = 1 << 11 + hwcap_NEON = 1 << 12 + hwcap_VFPv3 = 1 << 13 + hwcap_VFPv3D16 = 1 << 14 + hwcap_TLS = 1 << 15 + hwcap_VFPv4 = 1 << 16 + hwcap_IDIVA = 1 << 17 + hwcap_IDIVT = 1 << 18 + hwcap_VFPD32 = 1 << 19 + hwcap_LPAE = 1 << 20 + hwcap_EVTSTRM = 1 << 21 + + hwcap2_AES = 1 << 0 + hwcap2_PMULL = 1 << 1 + hwcap2_SHA1 = 1 << 2 + hwcap2_SHA2 = 1 << 3 + hwcap2_CRC32 = 1 << 4 +) diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go new file mode 100644 index 0000000..9c87677 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go @@ -0,0 +1,138 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import "runtime" + +const cacheLineSize = 64 + +func init() { + switch runtime.GOOS { + case "android", "darwin": + // Android and iOS don't seem to allow reading these registers. + // Fake the minimal features expected by + // TestARM64minimalFeatures. + ARM64.HasASIMD = true + ARM64.HasFP = true + case "linux": + doinit() + default: + readARM64Registers() + } +} + +func readARM64Registers() { + Initialized = true + + // ID_AA64ISAR0_EL1 + isar0 := getisar0() + + switch extractBits(isar0, 4, 7) { + case 1: + ARM64.HasAES = true + case 2: + ARM64.HasAES = true + ARM64.HasPMULL = true + } + + switch extractBits(isar0, 8, 11) { + case 1: + ARM64.HasSHA1 = true + } + + switch extractBits(isar0, 12, 15) { + case 1: + ARM64.HasSHA2 = true + case 2: + ARM64.HasSHA2 = true + ARM64.HasSHA512 = true + } + + switch extractBits(isar0, 16, 19) { + case 1: + ARM64.HasCRC32 = true + } + + switch extractBits(isar0, 20, 23) { + case 2: + ARM64.HasATOMICS = true + } + + switch extractBits(isar0, 28, 31) { + case 1: + ARM64.HasASIMDRDM = true + } + + switch extractBits(isar0, 32, 35) { + case 1: + ARM64.HasSHA3 = true + } + + switch extractBits(isar0, 36, 39) { + case 1: + ARM64.HasSM3 = true + } + + switch extractBits(isar0, 40, 43) { + case 1: + ARM64.HasSM4 = true + } + + switch extractBits(isar0, 44, 47) { + case 1: + ARM64.HasASIMDDP = true + } + + // ID_AA64ISAR1_EL1 + isar1 := getisar1() + + switch extractBits(isar1, 0, 3) { + case 1: + ARM64.HasDCPOP = true + } + + switch extractBits(isar1, 12, 15) { + case 1: + ARM64.HasJSCVT = true + } + + switch extractBits(isar1, 16, 19) { + case 1: + ARM64.HasFCMA = true + } + + switch extractBits(isar1, 20, 23) { + case 1: + ARM64.HasLRCPC = true + } + + // ID_AA64PFR0_EL1 + pfr0 := getpfr0() + + switch extractBits(pfr0, 16, 19) { + case 0: + ARM64.HasFP = true + case 1: + ARM64.HasFP = true + ARM64.HasFPHP = true + } + + switch extractBits(pfr0, 20, 23) { + case 0: + ARM64.HasASIMD = true + case 1: + ARM64.HasASIMD = true + ARM64.HasASIMDHP = true + } + + switch extractBits(pfr0, 32, 35) { + case 1: + ARM64.HasSVE = true + } +} + +func extractBits(data uint64, start, end uint) uint { + return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_arm64.s new file mode 100644 index 0000000..a54436e --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.s @@ -0,0 +1,31 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo + +#include "textflag.h" + +// func getisar0() uint64 +TEXT ·getisar0(SB),NOSPLIT,$0-8 + // get Instruction Set Attributes 0 into x0 + // mrs x0, ID_AA64ISAR0_EL1 = d5380600 + WORD $0xd5380600 + MOVD R0, ret+0(FP) + RET + +// func getisar1() uint64 +TEXT ·getisar1(SB),NOSPLIT,$0-8 + // get Instruction Set Attributes 1 into x0 + // mrs x0, ID_AA64ISAR1_EL1 = d5380620 + WORD $0xd5380620 + MOVD R0, ret+0(FP) + RET + +// func getpfr0() uint64 +TEXT ·getpfr0(SB),NOSPLIT,$0-8 + // get Processor Feature Register 0 into x0 + // mrs x0, ID_AA64PFR0_EL1 = d5380400 + WORD $0xd5380400 + MOVD R0, ret+0(FP) + RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go new file mode 100644 index 0000000..7b88e86 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go @@ -0,0 +1,11 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo + +package cpu + +func getisar0() uint64 +func getisar1() uint64 +func getpfr0() uint64 diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go new file mode 100644 index 0000000..568bcd0 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go @@ -0,0 +1,21 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo + +package cpu + +// haveAsmFunctions reports whether the other functions in this file can +// be safely called. +func haveAsmFunctions() bool { return true } + +// The following feature detection functions are defined in cpu_s390x.s. +// They are likely to be expensive to call so the results should be cached. +func stfle() facilityList +func kmQuery() queryResult +func kmcQuery() queryResult +func kmctrQuery() queryResult +func kmaQuery() queryResult +func kimdQuery() queryResult +func klmdQuery() queryResult diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go new file mode 100644 index 0000000..f7cb469 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -0,0 +1,16 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build !gccgo + +package cpu + +// cpuid is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) + +// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo.c for gccgo. +func xgetbv() (eax, edx uint32) diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go new file mode 100644 index 0000000..53ca8d6 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go @@ -0,0 +1,11 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gccgo + +package cpu + +func getisar0() uint64 { return 0 } +func getisar1() uint64 { return 0 } +func getpfr0() uint64 { return 0 } diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go new file mode 100644 index 0000000..aa986f7 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go @@ -0,0 +1,22 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gccgo + +package cpu + +// haveAsmFunctions reports whether the other functions in this file can +// be safely called. +func haveAsmFunctions() bool { return false } + +// TODO(mundaym): the following feature detection functions are currently +// stubs. See https://golang.org/cl/162887 for how to fix this. +// They are likely to be expensive to call so the results should be cached. +func stfle() facilityList { panic("not implemented for gccgo") } +func kmQuery() queryResult { panic("not implemented for gccgo") } +func kmcQuery() queryResult { panic("not implemented for gccgo") } +func kmctrQuery() queryResult { panic("not implemented for gccgo") } +func kmaQuery() queryResult { panic("not implemented for gccgo") } +func kimdQuery() queryResult { panic("not implemented for gccgo") } +func klmdQuery() queryResult { panic("not implemented for gccgo") } diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c new file mode 100644 index 0000000..e363c7d --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c @@ -0,0 +1,43 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build gccgo + +#include +#include + +// Need to wrap __get_cpuid_count because it's declared as static. +int +gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); +} + +// xgetbv reads the contents of an XCR (Extended Control Register) +// specified in the ECX register into registers EDX:EAX. +// Currently, the only supported value for XCR is 0. +// +// TODO: Replace with a better alternative: +// +// #include +// +// #pragma GCC target("xsave") +// +// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { +// unsigned long long x = _xgetbv(0); +// *eax = x & 0xffffffff; +// *edx = (x >> 32) & 0xffffffff; +// } +// +// Note that _xgetbv is defined starting with GCC 8. +void +gccgoXgetbv(uint32_t *eax, uint32_t *edx) +{ + __asm(" xorl %%ecx, %%ecx\n" + " xgetbv" + : "=a"(*eax), "=d"(*edx)); +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go new file mode 100644 index 0000000..ba49b91 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go @@ -0,0 +1,26 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 +// +build gccgo + +package cpu + +//extern gccgoGetCpuidCount +func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) + +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { + var a, b, c, d uint32 + gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) + return a, b, c, d +} + +//extern gccgoXgetbv +func gccgoXgetbv(eax, edx *uint32) + +func xgetbv() (eax, edx uint32) { + var a, d uint32 + gccgoXgetbv(&a, &d) + return a, d +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux.go b/vendor/golang.org/x/sys/cpu/cpu_linux.go new file mode 100644 index 0000000..fe13918 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux.go @@ -0,0 +1,15 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !386,!amd64,!amd64p32,!arm64 + +package cpu + +func init() { + if err := readHWCAP(); err != nil { + return + } + doinit() + Initialized = true +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go new file mode 100644 index 0000000..2057006 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go @@ -0,0 +1,39 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +func doinit() { + ARM.HasSWP = isSet(hwCap, hwcap_SWP) + ARM.HasHALF = isSet(hwCap, hwcap_HALF) + ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB) + ARM.Has26BIT = isSet(hwCap, hwcap_26BIT) + ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT) + ARM.HasFPA = isSet(hwCap, hwcap_FPA) + ARM.HasVFP = isSet(hwCap, hwcap_VFP) + ARM.HasEDSP = isSet(hwCap, hwcap_EDSP) + ARM.HasJAVA = isSet(hwCap, hwcap_JAVA) + ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT) + ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH) + ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE) + ARM.HasNEON = isSet(hwCap, hwcap_NEON) + ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3) + ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16) + ARM.HasTLS = isSet(hwCap, hwcap_TLS) + ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4) + ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA) + ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT) + ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32) + ARM.HasLPAE = isSet(hwCap, hwcap_LPAE) + ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) + ARM.HasAES = isSet(hwCap2, hwcap2_AES) + ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL) + ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1) + ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2) + ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go new file mode 100644 index 0000000..79a38a0 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go @@ -0,0 +1,71 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +// HWCAP/HWCAP2 bits. These are exposed by Linux. +const ( + hwcap_FP = 1 << 0 + hwcap_ASIMD = 1 << 1 + hwcap_EVTSTRM = 1 << 2 + hwcap_AES = 1 << 3 + hwcap_PMULL = 1 << 4 + hwcap_SHA1 = 1 << 5 + hwcap_SHA2 = 1 << 6 + hwcap_CRC32 = 1 << 7 + hwcap_ATOMICS = 1 << 8 + hwcap_FPHP = 1 << 9 + hwcap_ASIMDHP = 1 << 10 + hwcap_CPUID = 1 << 11 + hwcap_ASIMDRDM = 1 << 12 + hwcap_JSCVT = 1 << 13 + hwcap_FCMA = 1 << 14 + hwcap_LRCPC = 1 << 15 + hwcap_DCPOP = 1 << 16 + hwcap_SHA3 = 1 << 17 + hwcap_SM3 = 1 << 18 + hwcap_SM4 = 1 << 19 + hwcap_ASIMDDP = 1 << 20 + hwcap_SHA512 = 1 << 21 + hwcap_SVE = 1 << 22 + hwcap_ASIMDFHM = 1 << 23 +) + +func doinit() { + if err := readHWCAP(); err != nil { + // failed to read /proc/self/auxv, try reading registers directly + readARM64Registers() + return + } + + // HWCAP feature bits + ARM64.HasFP = isSet(hwCap, hwcap_FP) + ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD) + ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) + ARM64.HasAES = isSet(hwCap, hwcap_AES) + ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL) + ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1) + ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2) + ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32) + ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS) + ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP) + ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP) + ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID) + ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM) + ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT) + ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA) + ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC) + ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP) + ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3) + ARM64.HasSM3 = isSet(hwCap, hwcap_SM3) + ARM64.HasSM4 = isSet(hwCap, hwcap_SM4) + ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP) + ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) + ARM64.HasSVE = isSet(hwCap, hwcap_SVE) + ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go new file mode 100644 index 0000000..eb24e50 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go @@ -0,0 +1,22 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build mips64 mips64le + +package cpu + +// HWCAP bits. These are exposed by the Linux kernel 5.4. +const ( + // CPU features + hwcap_MIPS_MSA = 1 << 1 +) + +func doinit() { + // HWCAP feature bits + MIPS64X.HasMSA = isSet(hwCap, hwcap_MIPS_MSA) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go new file mode 100644 index 0000000..42b5d33 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go @@ -0,0 +1,9 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!s390x + +package cpu + +func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go new file mode 100644 index 0000000..6c8d975 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go @@ -0,0 +1,33 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux +// +build ppc64 ppc64le + +package cpu + +const cacheLineSize = 128 + +// HWCAP/HWCAP2 bits. These are exposed by the kernel. +const ( + // ISA Level + _PPC_FEATURE2_ARCH_2_07 = 0x80000000 + _PPC_FEATURE2_ARCH_3_00 = 0x00800000 + + // CPU features + _PPC_FEATURE2_DARN = 0x00200000 + _PPC_FEATURE2_SCV = 0x00100000 +) + +func doinit() { + // HWCAP2 feature bits + PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) + PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) + PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) + PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go new file mode 100644 index 0000000..d579eae --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go @@ -0,0 +1,161 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +const cacheLineSize = 256 + +const ( + // bit mask values from /usr/include/bits/hwcap.h + hwcap_ZARCH = 2 + hwcap_STFLE = 4 + hwcap_MSA = 8 + hwcap_LDISP = 16 + hwcap_EIMM = 32 + hwcap_DFP = 64 + hwcap_ETF3EH = 256 + hwcap_VX = 2048 + hwcap_VXE = 8192 +) + +// bitIsSet reports whether the bit at index is set. The bit index +// is in big endian order, so bit index 0 is the leftmost bit. +func bitIsSet(bits []uint64, index uint) bool { + return bits[index/64]&((1<<63)>>(index%64)) != 0 +} + +// function is the code for the named cryptographic function. +type function uint8 + +const ( + // KM{,A,C,CTR} function codes + aes128 function = 18 // AES-128 + aes192 function = 19 // AES-192 + aes256 function = 20 // AES-256 + + // K{I,L}MD function codes + sha1 function = 1 // SHA-1 + sha256 function = 2 // SHA-256 + sha512 function = 3 // SHA-512 + sha3_224 function = 32 // SHA3-224 + sha3_256 function = 33 // SHA3-256 + sha3_384 function = 34 // SHA3-384 + sha3_512 function = 35 // SHA3-512 + shake128 function = 36 // SHAKE-128 + shake256 function = 37 // SHAKE-256 + + // KLMD function codes + ghash function = 65 // GHASH +) + +// queryResult contains the result of a Query function +// call. Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type queryResult struct { + bits [2]uint64 +} + +// Has reports whether the given functions are present. +func (q *queryResult) Has(fns ...function) bool { + if len(fns) == 0 { + panic("no function codes provided") + } + for _, f := range fns { + if !bitIsSet(q.bits[:], uint(f)) { + return false + } + } + return true +} + +// facility is a bit index for the named facility. +type facility uint8 + +const ( + // cryptography facilities + msa4 facility = 77 // message-security-assist extension 4 + msa8 facility = 146 // message-security-assist extension 8 +) + +// facilityList contains the result of an STFLE call. +// Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type facilityList struct { + bits [4]uint64 +} + +// Has reports whether the given facilities are present. +func (s *facilityList) Has(fs ...facility) bool { + if len(fs) == 0 { + panic("no facility bits provided") + } + for _, f := range fs { + if !bitIsSet(s.bits[:], uint(f)) { + return false + } + } + return true +} + +func doinit() { + // test HWCAP bit vector + has := func(featureMask uint) bool { + return hwCap&featureMask == featureMask + } + + // mandatory + S390X.HasZARCH = has(hwcap_ZARCH) + + // optional + S390X.HasSTFLE = has(hwcap_STFLE) + S390X.HasLDISP = has(hwcap_LDISP) + S390X.HasEIMM = has(hwcap_EIMM) + S390X.HasETF3EH = has(hwcap_ETF3EH) + S390X.HasDFP = has(hwcap_DFP) + S390X.HasMSA = has(hwcap_MSA) + S390X.HasVX = has(hwcap_VX) + if S390X.HasVX { + S390X.HasVXE = has(hwcap_VXE) + } + + // We need implementations of stfle, km and so on + // to detect cryptographic features. + if !haveAsmFunctions() { + return + } + + // optional cryptographic functions + if S390X.HasMSA { + aes := []function{aes128, aes192, aes256} + + // cipher message + km, kmc := kmQuery(), kmcQuery() + S390X.HasAES = km.Has(aes...) + S390X.HasAESCBC = kmc.Has(aes...) + if S390X.HasSTFLE { + facilities := stfle() + if facilities.Has(msa4) { + kmctr := kmctrQuery() + S390X.HasAESCTR = kmctr.Has(aes...) + } + if facilities.Has(msa8) { + kma := kmaQuery() + S390X.HasAESGCM = kma.Has(aes...) + } + } + + // compute message digest + kimd := kimdQuery() // intermediate (no padding) + klmd := klmdQuery() // last (padding) + S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) + S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) + S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) + S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist + sha3 := []function{ + sha3_224, sha3_256, sha3_384, sha3_512, + shake128, shake256, + } + S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go new file mode 100644 index 0000000..6165f12 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build mips64 mips64le + +package cpu + +const cacheLineSize = 32 diff --git a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go new file mode 100644 index 0000000..1269eee --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build mips mipsle + +package cpu + +const cacheLineSize = 32 diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go new file mode 100644 index 0000000..3ffc4af --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go @@ -0,0 +1,9 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !linux,arm64 + +package cpu + +func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go new file mode 100644 index 0000000..efe2b7a --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go @@ -0,0 +1,9 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build riscv64 + +package cpu + +const cacheLineSize = 32 diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/vendor/golang.org/x/sys/cpu/cpu_s390x.s new file mode 100644 index 0000000..e5037d9 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_s390x.s @@ -0,0 +1,57 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo + +#include "textflag.h" + +// func stfle() facilityList +TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32 + MOVD $ret+0(FP), R1 + MOVD $3, R0 // last doubleword index to store + XC $32, (R1), (R1) // clear 4 doublewords (32 bytes) + WORD $0xb2b01000 // store facility list extended (STFLE) + RET + +// func kmQuery() queryResult +TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KM-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB92E0024 // cipher message (KM) + RET + +// func kmcQuery() queryResult +TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KMC-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB92F0024 // cipher message with chaining (KMC) + RET + +// func kmctrQuery() queryResult +TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KMCTR-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB92D4024 // cipher message with counter (KMCTR) + RET + +// func kmaQuery() queryResult +TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KMA-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xb9296024 // cipher message with authentication (KMA) + RET + +// func kimdQuery() queryResult +TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KIMD-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB93E0024 // compute intermediate message digest (KIMD) + RET + +// func klmdQuery() queryResult +TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16 + MOVD $0, R0 // set function code to 0 (KLMD-Query) + MOVD $ret+0(FP), R1 // address of 16-byte return value + WORD $0xB93F0024 // compute last message digest (KLMD) + RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_wasm.go b/vendor/golang.org/x/sys/cpu/cpu_wasm.go new file mode 100644 index 0000000..8681e87 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_wasm.go @@ -0,0 +1,13 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build wasm + +package cpu + +// We're compiling the cpu package for an unknown (software-abstracted) CPU. +// Make CacheLinePad an empty struct and hope that the usual struct alignment +// rules are good enough. + +const cacheLineSize = 0 diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go new file mode 100644 index 0000000..d70d317 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -0,0 +1,59 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build 386 amd64 amd64p32 + +package cpu + +const cacheLineSize = 64 + +func init() { + Initialized = true + + maxID, _, _, _ := cpuid(0, 0) + + if maxID < 1 { + return + } + + _, _, ecx1, edx1 := cpuid(1, 0) + X86.HasSSE2 = isSet(26, edx1) + + X86.HasSSE3 = isSet(0, ecx1) + X86.HasPCLMULQDQ = isSet(1, ecx1) + X86.HasSSSE3 = isSet(9, ecx1) + X86.HasFMA = isSet(12, ecx1) + X86.HasSSE41 = isSet(19, ecx1) + X86.HasSSE42 = isSet(20, ecx1) + X86.HasPOPCNT = isSet(23, ecx1) + X86.HasAES = isSet(25, ecx1) + X86.HasOSXSAVE = isSet(27, ecx1) + X86.HasRDRAND = isSet(30, ecx1) + + osSupportsAVX := false + // For XGETBV, OSXSAVE bit is required and sufficient. + if X86.HasOSXSAVE { + eax, _ := xgetbv() + // Check if XMM and YMM registers have OS support. + osSupportsAVX = isSet(1, eax) && isSet(2, eax) + } + + X86.HasAVX = isSet(28, ecx1) && osSupportsAVX + + if maxID < 7 { + return + } + + _, ebx7, _, _ := cpuid(7, 0) + X86.HasBMI1 = isSet(3, ebx7) + X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX + X86.HasBMI2 = isSet(8, ebx7) + X86.HasERMS = isSet(9, ebx7) + X86.HasRDSEED = isSet(18, ebx7) + X86.HasADX = isSet(19, ebx7) +} + +func isSet(bitpos uint, value uint32) bool { + return value&(1<> 63)) +) + +// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2 +// These are initialized in cpu_$GOARCH.go +// and should not be changed after they are initialized. +var hwCap uint +var hwCap2 uint + +func readHWCAP() error { + buf, err := ioutil.ReadFile(procAuxv) + if err != nil { + // e.g. on android /proc/self/auxv is not accessible, so silently + // ignore the error and leave Initialized = false. On some + // architectures (e.g. arm64) doinit() implements a fallback + // readout and will set Initialized = true again. + return err + } + bo := hostByteOrder() + for len(buf) >= 2*(uintSize/8) { + var tag, val uint + switch uintSize { + case 32: + tag = uint(bo.Uint32(buf[0:])) + val = uint(bo.Uint32(buf[4:])) + buf = buf[8:] + case 64: + tag = uint(bo.Uint64(buf[0:])) + val = uint(bo.Uint64(buf[8:])) + buf = buf[16:] + } + switch tag { + case _AT_HWCAP: + hwCap = val + case _AT_HWCAP2: + hwCap2 = val + } + } + return nil +} diff --git a/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go new file mode 100644 index 0000000..78fe25e --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go @@ -0,0 +1,36 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Minimal copy of x/sys/unix so the cpu package can make a +// system call on AIX without depending on x/sys/unix. +// (See golang.org/issue/32102) + +// +build aix,ppc64 +// +build !gccgo + +package cpu + +import ( + "syscall" + "unsafe" +) + +//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o" + +//go:linkname libc_getsystemcfg libc_getsystemcfg + +type syscallFunc uintptr + +var libc_getsystemcfg syscallFunc + +type errno = syscall.Errno + +// Implemented in runtime/syscall_aix.go. +func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) +func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) + +func callgetsystemcfg(label int) (r1 uintptr, e1 errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsystemcfg)), 1, uintptr(label), 0, 0, 0, 0, 0) + return +} diff --git a/vendor/modules.txt b/vendor/modules.txt new file mode 100644 index 0000000..5c6efbf --- /dev/null +++ b/vendor/modules.txt @@ -0,0 +1,7 @@ +# github.com/andy2046/gopie v0.7.0 +github.com/andy2046/gopie/pkg/dll +github.com/andy2046/gopie/pkg/log +# github.com/andy2046/maths v0.1.0 +github.com/andy2046/maths +# golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f +golang.org/x/sys/cpu