From 7bb55be855270fd6a0ab74a4c07c31687758b5ba Mon Sep 17 00:00:00 2001 From: cnderrauber Date: Mon, 1 Jul 2024 15:36:57 +0800 Subject: [PATCH] Remove third-party dequeue Remove third-party dequeue --- go.mod | 1 - go.sum | 2 -- payload_queue.go | 6 ++-- queue.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ queue_test.go | 48 +++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 queue.go create mode 100644 queue_test.go diff --git a/go.mod b/go.mod index 42fa5eb4..2f004cae 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,6 @@ module github.com/pion/sctp require ( - github.com/gammazero/deque v0.2.1 github.com/pion/logging v0.2.2 github.com/pion/randutil v0.1.0 github.com/pion/transport/v3 v3.0.2 diff --git a/go.sum b/go.sum index 92a3c047..25392e78 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= -github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/payload_queue.go b/payload_queue.go index 7ee8820a..92eacecd 100644 --- a/payload_queue.go +++ b/payload_queue.go @@ -3,15 +3,13 @@ package sctp -import "github.com/gammazero/deque" - type payloadQueue struct { - chunks *deque.Deque[*chunkPayloadData] + chunks *queue[*chunkPayloadData] nBytes int } func newPayloadQueue() *payloadQueue { - return &payloadQueue{chunks: deque.New[*chunkPayloadData](128)} + return &payloadQueue{chunks: newQueue[*chunkPayloadData](128)} } func (q *payloadQueue) pushNoCheck(p *chunkPayloadData) { diff --git a/queue.go b/queue.go new file mode 100644 index 00000000..e089973a --- /dev/null +++ b/queue.go @@ -0,0 +1,78 @@ +package sctp + +import "fmt" + +type queue[T any] struct { + buf []T + head int + tail int + count int +} + +const minCap = 16 + +func newQueue[T any](capacity int) *queue[T] { + queueCap := minCap + for queueCap < capacity { + queueCap <<= 1 + } + + return &queue[T]{ + buf: make([]T, queueCap), + } +} + +func (q *queue[T]) Len() int { + return q.count +} + +func (q *queue[T]) PushBack(ele T) { + q.growIfFull() + q.buf[q.tail] = ele + q.tail = (q.tail + 1) % len(q.buf) + q.count++ +} + +func (q *queue[T]) PopFront() T { + if q.count <= 0 { + panic("PopFront() called on empty queue") + } + ele := q.buf[q.head] + var zeroVal T + q.buf[q.head] = zeroVal + q.head = (q.head + 1) % len(q.buf) + q.count-- + return ele +} + +func (q *queue[T]) Front() T { + if q.count <= 0 { + panic("Front() called on empty queue") + } + return q.buf[q.head] +} + +func (q *queue[T]) At(i int) T { + if i < 0 || i >= q.count { + panic(fmt.Sprintf("index %d out of range %d", i, q.count)) + } + return q.buf[(q.head+i)%(len(q.buf))] +} + +func (q *queue[T]) growIfFull() { + if q.count < len(q.buf) { + return + } + + newBuf := make([]T, q.count<<1) + if q.tail > q.head { + copy(newBuf, q.buf[q.head:q.tail]) + } else { + n := copy(newBuf, q.buf[q.head:]) + copy(newBuf[n:], q.buf[:q.tail]) + } + + q.head = 0 + q.tail = q.count + q.buf = newBuf +} diff --git a/queue_test.go b/queue_test.go new file mode 100644 index 00000000..522ab15c --- /dev/null +++ b/queue_test.go @@ -0,0 +1,48 @@ +package sctp + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestQueue(t *testing.T) { + q := newQueue[int](32) + assert.Panics(t, func() { q.PopFront() }) + assert.Panics(t, func() { q.Front() }) + assert.Zero(t, q.Len()) + + // test push & pop + for i := 1; i < 33; i++ { + q.PushBack(i) + } + assert.Equal(t, 32, q.Len()) + assert.Equal(t, 5, q.At(4)) + for i := 1; i < 33; i++ { + assert.Equal(t, i, q.Front()) + assert.Equal(t, i, q.PopFront()) + } + assert.Zero(t, q.Len()) + + q.PushBack(10) + q.PushBack(11) + assert.Equal(t, 2, q.Len()) + assert.Equal(t, 11, q.At(1)) + assert.Equal(t, 10, q.Front()) + assert.Panics(t, func() { + q.At(33) + }) + assert.Equal(t, 10, q.PopFront()) + assert.Equal(t, 11, q.PopFront()) + + // test grow capacity + for i := 0; i < 64; i++ { + q.PushBack(i) + } + assert.Equal(t, 64, q.Len()) + assert.Equal(t, 2, q.At(2)) + for i := 0; i < 64; i++ { + assert.Equal(t, i, q.Front()) + assert.Equal(t, i, q.PopFront()) + } +}