Bumps the go-modules-updates group with 11 updates in the /backend directory: | Package | From | To | | --- | --- | --- | | [github.com/PuerkitoBio/goquery](https://github.com/PuerkitoBio/goquery) | `1.10.2` | `1.11.0` | | [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) | `2.15.0` | `2.20.0` | | [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) | `5.2.1` | `5.2.3` | | [github.com/go-chi/cors](https://github.com/go-chi/cors) | `1.2.1` | `1.2.2` | | [github.com/go-pkgz/jrpc](https://github.com/go-pkgz/jrpc) | `0.3.1` | `0.4.0` | | [github.com/go-pkgz/lgr](https://github.com/go-pkgz/lgr) | `0.12.0` | `0.12.1` | | [github.com/go-pkgz/rest](https://github.com/go-pkgz/rest) | `1.20.3` | `1.20.4` | | [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) | `5.2.2` | `5.3.0` | | [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.10.0` | `1.11.1` | | [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) | `1.4.0` | `1.4.3` | | [golang.org/x/image](https://github.com/golang/image) | `0.26.0` | `0.33.0` | Updates `github.com/PuerkitoBio/goquery` from 1.10.2 to 1.11.0 - [Release notes](https://github.com/PuerkitoBio/goquery/releases) - [Commits](https://github.com/PuerkitoBio/goquery/compare/v1.10.2...v1.11.0) Updates `github.com/alecthomas/chroma/v2` from 2.15.0 to 2.20.0 - [Release notes](https://github.com/alecthomas/chroma/releases) - [Commits](https://github.com/alecthomas/chroma/compare/v2.15.0...v2.20.0) Updates `github.com/go-chi/chi/v5` from 5.2.1 to 5.2.3 - [Release notes](https://github.com/go-chi/chi/releases) - [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md) - [Commits](https://github.com/go-chi/chi/compare/v5.2.1...v5.2.3) Updates `github.com/go-chi/cors` from 1.2.1 to 1.2.2 - [Release notes](https://github.com/go-chi/cors/releases) - [Commits](https://github.com/go-chi/cors/compare/v1.2.1...v1.2.2) Updates `github.com/go-pkgz/jrpc` from 0.3.1 to 0.4.0 - [Release notes](https://github.com/go-pkgz/jrpc/releases) - [Commits](https://github.com/go-pkgz/jrpc/compare/v0.3.1...v0.4.0) Updates `github.com/go-pkgz/lgr` from 0.12.0 to 0.12.1 - [Release notes](https://github.com/go-pkgz/lgr/releases) - [Commits](https://github.com/go-pkgz/lgr/compare/v0.12.0...v0.12.1) Updates `github.com/go-pkgz/rest` from 1.20.3 to 1.20.4 - [Release notes](https://github.com/go-pkgz/rest/releases) - [Commits](https://github.com/go-pkgz/rest/compare/v1.20.3...v1.20.4) Updates `github.com/golang-jwt/jwt/v5` from 5.2.2 to 5.3.0 - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.2...v5.3.0) Updates `github.com/stretchr/testify` from 1.10.0 to 1.11.1 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.10.0...v1.11.1) Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.3 - [Release notes](https://github.com/etcd-io/bbolt/releases) - [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.3) Updates `golang.org/x/image` from 0.26.0 to 0.33.0 - [Commits](https://github.com/golang/image/compare/v0.26.0...v0.33.0) --- updated-dependencies: - dependency-name: github.com/PuerkitoBio/goquery dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/alecthomas/chroma/v2 dependency-version: 2.20.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/go-chi/chi/v5 dependency-version: 5.2.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/go-chi/cors dependency-version: 1.2.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/go-pkgz/jrpc dependency-version: 0.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/go-pkgz/lgr dependency-version: 0.12.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/go-pkgz/rest dependency-version: 1.20.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/golang-jwt/jwt/v5 dependency-version: 5.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/stretchr/testify dependency-version: 1.11.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: go.etcd.io/bbolt dependency-version: 1.4.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: golang.org/x/image dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates ... Signed-off-by: dependabot[bot] <support@github.com>
142 lines
4.0 KiB
Go
142 lines
4.0 KiB
Go
package regexp2
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// fasttime holds a time value (ticks since clock initialization)
|
|
type fasttime int64
|
|
|
|
// fastclock provides a fast clock implementation.
|
|
//
|
|
// A background goroutine periodically stores the current time
|
|
// into an atomic variable.
|
|
//
|
|
// A deadline can be quickly checked for expiration by comparing
|
|
// its value to the clock stored in the atomic variable.
|
|
//
|
|
// The goroutine automatically stops once clockEnd is reached.
|
|
// (clockEnd covers the largest deadline seen so far + some
|
|
// extra time). This ensures that if regexp2 with timeouts
|
|
// stops being used we will stop background work.
|
|
type fastclock struct {
|
|
// instances of atomicTime must be at the start of the struct (or at least 64-bit aligned)
|
|
// otherwise 32-bit architectures will panic
|
|
|
|
current atomicTime // Current time (approximate)
|
|
clockEnd atomicTime // When clock updater is supposed to stop (>= any existing deadline)
|
|
|
|
// current and clockEnd can be read via atomic loads.
|
|
// Reads and writes of other fields require mu to be held.
|
|
mu sync.Mutex
|
|
start time.Time // Time corresponding to fasttime(0)
|
|
running bool // Is a clock updater running?
|
|
}
|
|
|
|
var fast fastclock
|
|
|
|
// reached returns true if current time is at or past t.
|
|
func (t fasttime) reached() bool {
|
|
return fast.current.read() >= t
|
|
}
|
|
|
|
// makeDeadline returns a time that is approximately time.Now().Add(d)
|
|
func makeDeadline(d time.Duration) fasttime {
|
|
// Increase the deadline since the clock we are reading may be
|
|
// just about to tick forwards.
|
|
end := fast.current.read() + durationToTicks(d+clockPeriod)
|
|
|
|
// Start or extend clock if necessary.
|
|
if end > fast.clockEnd.read() {
|
|
// If time.Since(last use) > timeout, there's a chance that
|
|
// fast.current will no longer be updated, which can lead to
|
|
// incorrect 'end' calculations that can trigger a false timeout
|
|
fast.mu.Lock()
|
|
if !fast.running && !fast.start.IsZero() {
|
|
// update fast.current
|
|
fast.current.write(durationToTicks(time.Since(fast.start)))
|
|
// recalculate our end value
|
|
end = fast.current.read() + durationToTicks(d+clockPeriod)
|
|
}
|
|
fast.mu.Unlock()
|
|
extendClock(end)
|
|
}
|
|
|
|
return end
|
|
}
|
|
|
|
// extendClock ensures that clock is live and will run until at least end.
|
|
func extendClock(end fasttime) {
|
|
fast.mu.Lock()
|
|
defer fast.mu.Unlock()
|
|
|
|
if fast.start.IsZero() {
|
|
fast.start = time.Now()
|
|
}
|
|
|
|
// Extend the running time to cover end as well as a bit of slop.
|
|
if shutdown := end + durationToTicks(time.Second); shutdown > fast.clockEnd.read() {
|
|
fast.clockEnd.write(shutdown)
|
|
}
|
|
|
|
// Start clock if necessary
|
|
if !fast.running {
|
|
fast.running = true
|
|
go runClock()
|
|
}
|
|
}
|
|
|
|
// stop the timeout clock in the background
|
|
// should only used for unit tests to abandon the background goroutine
|
|
func stopClock() {
|
|
fast.mu.Lock()
|
|
if fast.running {
|
|
fast.clockEnd.write(fasttime(0))
|
|
}
|
|
fast.mu.Unlock()
|
|
|
|
// pause until not running
|
|
// get and release the lock
|
|
isRunning := true
|
|
for isRunning {
|
|
time.Sleep(clockPeriod / 2)
|
|
fast.mu.Lock()
|
|
isRunning = fast.running
|
|
fast.mu.Unlock()
|
|
}
|
|
}
|
|
|
|
func durationToTicks(d time.Duration) fasttime {
|
|
// Downscale nanoseconds to approximately a millisecond so that we can avoid
|
|
// overflow even if the caller passes in math.MaxInt64.
|
|
return fasttime(d) >> 20
|
|
}
|
|
|
|
const DefaultClockPeriod = 100 * time.Millisecond
|
|
|
|
// clockPeriod is the approximate interval between updates of approximateClock.
|
|
var clockPeriod = DefaultClockPeriod
|
|
|
|
func runClock() {
|
|
fast.mu.Lock()
|
|
defer fast.mu.Unlock()
|
|
|
|
for fast.current.read() <= fast.clockEnd.read() {
|
|
// Unlock while sleeping.
|
|
fast.mu.Unlock()
|
|
time.Sleep(clockPeriod)
|
|
fast.mu.Lock()
|
|
|
|
newTime := durationToTicks(time.Since(fast.start))
|
|
fast.current.write(newTime)
|
|
}
|
|
fast.running = false
|
|
}
|
|
|
|
type atomicTime struct{ v int64 } // Should change to atomic.Int64 when we can use go 1.19
|
|
|
|
func (t *atomicTime) read() fasttime { return fasttime(atomic.LoadInt64(&t.v)) }
|
|
func (t *atomicTime) write(v fasttime) { atomic.StoreInt64(&t.v, int64(v)) }
|