1
2
mirror of https://github.com/yunginnanet/Rate5 synced 2024-06-27 01:18:37 +00:00

Compare commits

..

No commits in common. "d30d1734623bd6d58c80f705361ce4eb4cd98eb3" and "ce01a166263981489791c7586c678143e2e4c646" have entirely different histories.

5 changed files with 135 additions and 12 deletions

@ -1,7 +1,7 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
@ -9,7 +9,3 @@ updates:
directory: "/" # Location of package manifests
schedule:
interval: "daily"
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

@ -38,11 +38,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -53,7 +53,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -67,4 +67,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v1

@ -6,12 +6,12 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
fetch-depth: 2
- uses: actions/setup-go@v4
- uses: actions/setup-go@v2
with:
go-version: '1.21'
go-version: '1.17'
- name: Run coverage
run: go test -v -race -coverprofile=coverage.txt -covermode=atomic ./...
- name: Upload coverage to Codecov

5
queue/errors.go Normal file

@ -0,0 +1,5 @@
package queue
import "errors"
var ErrQueueFull = errors.New("bounded queue is full")

122
queue/queue.go Normal file

@ -0,0 +1,122 @@
package queue
import (
"fmt"
"sync"
"sync/atomic"
"git.tcp.direct/kayos/common/list"
"golang.org/x/exp/constraints"
)
type Item[P constraints.Ordered, V any] struct {
value *V
priority P
index int
}
func NewItem[P constraints.Ordered, V any](v *V, p P) *Item[P, V] {
return &Item[P, V]{
value: v,
priority: p,
index: 0,
}
}
func (i *Item[P, V]) Less(j any) bool {
return i.priority < j.(Item[P, V]).priority
}
func (i *Item[P, V]) Value() *V {
return i.value
}
func (i *Item[P, V]) Priority() P {
return i.priority
}
func (i *Item[P, V]) Set(v *V) {
i.value = v
}
func (i *Item[P, V]) SetPriority(p P) {
i.priority = p
}
type boundedQueue[P constraints.Ordered, V any] struct {
items []*Item[P, V]
qcap int64
qlen *atomic.Int64
mu *sync.RWMutex
errs *list.LockingList
}
type BoundedQueue[P constraints.Ordered, V any] struct {
// making sure container/heap can access boundedQueue without the normal API being exposed to the user
inner *boundedQueue[P, V]
}
func NewBoundedQueue[P constraints.Ordered, V any](cap int64) *BoundedQueue[P, V] {
bq := &BoundedQueue[P, V]{}
bq.inner = &boundedQueue[P, V]{
items: make([]*Item[P, V], 0, cap),
qcap: cap,
qlen: &atomic.Int64{},
mu: &sync.RWMutex{},
errs: list.New(),
}
bq.inner.qlen.Store(0)
return bq
}
func (b *boundedQueue[P, V]) err(err error) {
b.errs.PushBack(err)
}
func (b *BoundedQueue[P, V]) Err() error {
errLen := b.inner.errs.Len()
switch errLen {
case 0:
return nil
case 1:
return b.inner.errs.Front().Value().(error)
default:
return fmt.Errorf("%w | (%d more errors in queue)", b.inner.errs.Front().Value().(error), errLen-1)
}
}
func (b *BoundedQueue[P, V]) Len() int {
return int(b.inner.qlen.Load())
}
func (b *boundedQueue[P, V]) Less(i, j int) bool {
b.mu.RLock()
less := b.items[P, V][i].priority < b.items[P, V][j].priority
b.mu.RUnlock()
return less
}
func (b *boundedQueue[P, V]) Swap(i, j int) {
b.mu.Lock()
b.items[P, V][i], b.items[P, V][j] = b.items[P, V][j], b.items[P, V][i]
b.items[P, V][i].index = i
b.items[P, V][j].index = j
b.mu.Unlock()
}
func (b *boundedQueue[P, V]) Push(x any) {
if b.qlen.Load() >= b.qcap {
b.err(fmt.Errorf("%w: %v dropped", ErrQueueFull, x))
return
}
defer b.qlen.Add(1)
b.mu.Lock()
b.items[P, V] = append(b.items[P, V], x.(*Item[P, V]))
b.qlen.Add(1)
b.mu.Unlock()
}
func (b *boundedQueue[P, V]) Pop() any {
// todo
return nil
}