Skip to content

Commit

Permalink
[TASK] TRK-2258 Add FIFO queue (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
Skandalik authored Oct 19, 2023
1 parent 8d09eb0 commit a858114
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 4 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ '1.18', '1.19.x' ]
go-version: [ '1.21', '1.21.x' ]

steps:
- name: Checkout the repository
Expand All @@ -26,7 +26,7 @@ jobs:
run: go version

- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@2022.1.3
run: go install honnef.co/go/tools/cmd/staticcheck@latest

- name: Install cover
run: go get -u golang.org/x/tools/cmd/cover
Expand All @@ -38,7 +38,7 @@ jobs:
run: go get -u github.com/mattn/goveralls

- name: Staticcheck
run: staticcheck -checks="all,-ST1000" github.com/msales/gox/...
run: staticcheck -checks="all,-ST1000,-SA1019" github.com/msales/gox/...

- name: Vet
run: go vet ./...
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/msales/gox

go 1.16
go 1.21
48 changes: 48 additions & 0 deletions queuex/fifo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package queuex

import "sync"

// FIFO is simple implementation of FIFO (first-in-first-out) queue with locks.
type FIFO[T any] struct {
m sync.Mutex

vals []T
}

// NewFIFO initializes queue with values.
func NewFIFO[T any](vals ...T) *FIFO[T] {
return &FIFO[T]{vals: vals}
}

// Push adds elements at the end of the queue.
func (f *FIFO[T]) Push(v T) *FIFO[T] {
f.m.Lock()
defer f.m.Unlock()

f.vals = append(f.vals, v)
return f
}

// Pop returns first element from the queue.
// Bool is also returned to indicate if queue has run out of the values.
func (f *FIFO[T]) Pop() (T, bool) {
f.m.Lock()
defer f.m.Unlock()

if len(f.vals) == 0 {
var t T
return t, false
}

v := f.vals[0]
f.vals = f.vals[1:]
return v, true
}

// Len returns length of queue.
func (f *FIFO[T]) Len() int {
f.m.Lock()
defer f.m.Unlock()

return len(f.vals)
}
146 changes: 146 additions & 0 deletions queuex/fifo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package queuex_test

import (
"github.com/msales/gox/queuex"
"testing"
)

func TestFIFO(t *testing.T) {
queue := queuex.NewFIFO([]int{
1, 2,
}...)

queue.Push(3)

got, ok := queue.Pop()
wantVal := 1
wantOK := true
if wantVal != got {
t.Errorf("Got %+v, want %+v", got, wantVal)
}

if ok != wantOK {
t.Errorf("Got %+v, want %+v", ok, wantOK)
}

got, ok = queue.Pop()
wantVal = 2
wantOK = true
if wantVal != got {
t.Errorf("Got %+v, want %+v", got, wantVal)
}

if ok != wantOK {
t.Errorf("Got %+v, want %+v", ok, wantOK)
}

got, ok = queue.Pop()
wantVal = 3
wantOK = true
if wantVal != got {
t.Errorf("Got %+v, want %+v", got, wantVal)
}

if ok != wantOK {
t.Errorf("Got %+v, want %+v", ok, wantOK)
}

got, ok = queue.Pop()
wantVal = 0
wantOK = false
if wantVal != got {
t.Errorf("Got %+v, want %+v", got, wantVal)
}

if ok != wantOK {
t.Errorf("Got %+v, want %+v", ok, wantOK)
}
}

func TestFIFO_EmptyQueue(t *testing.T) {
queue := queuex.NewFIFO[int]()

got, ok := queue.Pop()
wantVal := 0
wantOK := false
if wantVal != got {
t.Errorf("Got %+v, want %+v", got, wantVal)
}

if ok != wantOK {
t.Errorf("Got %+v, want %+v", ok, wantOK)
}

got, ok = queue.Pop()
if wantVal != got {
t.Errorf("Got %+v, want %+v", got, wantVal)
}

if ok != wantOK {
t.Errorf("Got %+v, want %+v", ok, wantOK)
}
}

func BenchmarkFIFO_Pop(b *testing.B) {
vals := make([]int, 1000)
for i := 0; i < 1000; i++ {
vals[i] = i
}

queue := queuex.NewFIFO(vals...)

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
queue.Pop()
}
}

func BenchmarkFIFO_Push(b *testing.B) {
vals := make([]int, 1000)
for i := 0; i < 1000; i++ {
vals[i] = i
}

queue := queuex.NewFIFO(vals...)

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
queue.Push(i)
}
}

func BenchmarkFIFO_EmptyPush(b *testing.B) {
queue := queuex.NewFIFO[int]()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
queue.Push(i)
}
}

func BenchmarkFIFO_RandomPushPop(b *testing.B) {
vals := make([]int, 1000)
for i := 0; i < 1000; i++ {
vals[i] = i
}

queue := queuex.NewFIFO(vals...)

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
if i%2 == 0 {
queue.Pop()
continue
} else {
queue.Push(i)
}
}
}

0 comments on commit a858114

Please sign in to comment.