From ed87951d6bd4ecd82ffd0bd6701ae88a5b2e9a9e Mon Sep 17 00:00:00 2001 From: qydysky Date: Tue, 4 Feb 2025 18:14:43 +0800 Subject: [PATCH] 1 (#20) --- .github/workflows/test1.yml | 6 +- slice/FIFO.go | 130 ++++++++++++++++++++++++++++++++++++ slice/FIFO_test.go | 94 ++++++++++++++++++++++++++ 3 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 slice/FIFO.go create mode 100644 slice/FIFO_test.go diff --git a/.github/workflows/test1.yml b/.github/workflows/test1.yml index 1c9565c..d5401a4 100644 --- a/.github/workflows/test1.yml +++ b/.github/workflows/test1.yml @@ -38,7 +38,7 @@ jobs: go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component2 go test -count 1 -timeout 20s -v -race github.com/qydysky/part/ctx - go test -count 1 -timeout 7s -v -race github.com/qydysky/part/slice + go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto @@ -77,7 +77,7 @@ jobs: go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component2 go test -count 1 -timeout 20s -v -race github.com/qydysky/part/ctx - go test -count 1 -timeout 7s -v -race github.com/qydysky/part/slice + go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto @@ -116,7 +116,7 @@ jobs: go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component2 go test -count 1 -timeout 20s -v -race github.com/qydysky/part/ctx - go test -count 1 -timeout 7s -v -race github.com/qydysky/part/slice + go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto diff --git a/slice/FIFO.go b/slice/FIFO.go new file mode 100644 index 0000000..01f2311 --- /dev/null +++ b/slice/FIFO.go @@ -0,0 +1,130 @@ +package part + +import ( + "sync" + + "errors" +) + +var ( + ErrFIFOOverflow = errors.New(`ErrFIFOOverflow`) + ErrFIFOEmpty = errors.New(`ErrFIFOEmpty`) +) + +type item struct { + op, ed int +} + +type FIFO[S any, T []S] struct { + ed, op, opc int + c chan item + buf []S + l sync.RWMutex +} + +func NewFIFO[S any, T []S](size int) *FIFO[S, T] { + return &FIFO[S, T]{ + c: make(chan item, size), + buf: make([]S, size), + } +} + +func (t *FIFO[S, T]) lock() func() { + t.l.Lock() + return t.l.Unlock +} + +func (t *FIFO[S, T]) rlock() func() { + t.l.RLock() + return t.l.RUnlock +} + +func (t *FIFO[S, T]) inok(size int) bool { + if t.ed+size > len(t.buf) { + if size > t.op { + return false + } + t.ed = 0 + } else if t.op > t.ed && t.ed+size > t.op { + return false + } + return true +} + +func (t *FIFO[S, T]) In(p T) error { + defer t.lock()() + + t.op = t.opc + if !t.inok(len(p)) { + return ErrFIFOOverflow + } + select { + case t.c <- item{ + op: t.ed, + ed: t.ed + len(p), + }: + t.ed = t.ed + copy(t.buf[t.ed:], p) + default: + return ErrFIFOOverflow + } + return nil +} + +func (t *FIFO[S, T]) Out() (p T, e error) { + defer t.rlock()() + + select { + case item := <-t.c: + p = t.buf[item.op:item.ed] + t.opc = item.ed + default: + e = ErrFIFOEmpty + } + + return +} + +func (t *FIFO[S, T]) Size() int { + defer t.rlock()() + + if t.opc > t.ed { + return len(t.buf) - t.opc - t.ed + } else { + return t.ed - t.opc + } +} + +func (t *FIFO[S, T]) Num() int { + return len(t.c) +} + +func (t *FIFO[S, T]) Clear() { + defer t.lock()() + + t.op = 0 + t.opc = 0 + t.ed = 0 + for { + select { + case <-t.c: + default: + return + } + } +} + +func (t *FIFO[S, T]) Reset() { + defer t.lock()() + + clear(t.buf) + t.op = 0 + t.opc = 0 + t.ed = 0 + for { + select { + case <-t.c: + default: + return + } + } +} diff --git a/slice/FIFO_test.go b/slice/FIFO_test.go new file mode 100644 index 0000000..4c8676f --- /dev/null +++ b/slice/FIFO_test.go @@ -0,0 +1,94 @@ +package part + +import ( + "bytes" + "testing" +) + +func TestFIFO(t *testing.T) { + fifo := NewFIFO[byte](5) + + if fifo.In([]byte("012345")) != ErrFIFOOverflow { + t.Fatal() + } + fifo.Clear() + + if fifo.In([]byte("012")) != nil { + t.Fatal() + } + if fifo.In([]byte("345")) != ErrFIFOOverflow { + t.Fatal() + } + fifo.Clear() + + if fifo.In([]byte("012")) != nil { + t.Fatal() + } + if fifo.In([]byte("34")) != nil { + t.Fatal() + } + fifo.Clear() + + if fifo.In([]byte("012")) != nil { + t.Fatal() + } + if tmp, e := fifo.Out(); e != nil || !bytes.Equal(tmp, []byte("012")) { + t.Fatal() + } + fifo.Clear() + + if fifo.In([]byte("01")) != nil { + t.Fatal() + } + if fifo.Size() != 2 { + t.Fatal() + } + if e := fifo.In([]byte("234")); e != nil { + t.Fatal(e) + } + if fifo.Size() != 5 { + t.Fatal() + } + if tmp, e := fifo.Out(); e != nil || !bytes.Equal(tmp, []byte("01")) { + t.Fatal() + } + if fifo.In([]byte("56")) != nil { + t.Fatal() + } + if tmp, e := fifo.Out(); e != nil || !bytes.Equal(tmp, []byte("234")) { + t.Fatal() + } + if tmp, e := fifo.Out(); e != nil || !bytes.Equal(tmp, []byte("56")) { + t.Fatal() + } + fifo.Clear() + + // if fifo.In([]byte("012")) != nil { + // t.Fatal() + // } + // go func() { + // time.Sleep(time.Millisecond * 500) + // fifo.Out() + // }() + // if e := fifo.In([]byte("345")); e != nil { + // t.Fatal(e) + // } + // time.Sleep(time.Second * 10) + // fifo.Clear() +} + +func BenchmarkFIFO(b *testing.B) { + fifo := NewFIFO[byte](5) + buf := []byte("12") + b.ResetTimer() + for i := 0; i < b.N; i++ { + if e := fifo.In(buf); e != nil { + b.FailNow() + } + if fifo.Num() > 1 { + if tmp, e := fifo.Out(); e != nil || !bytes.Equal(tmp, buf) { + b.FailNow() + } + } + } +} -- 2.39.2