From 0ea90952bdac100bde3149fa2a7818ba7af943b4 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Fri, 22 Mar 2024 17:00:10 +0100 Subject: pkg/fuzzer: remove async priority queue operations We don't need them. --- pkg/fuzzer/prio_queue.go | 29 ++++++++--------------------- pkg/fuzzer/prio_queue_test.go | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 36 deletions(-) (limited to 'pkg/fuzzer') diff --git a/pkg/fuzzer/prio_queue.go b/pkg/fuzzer/prio_queue.go index ea8f448c9..cb35cebf7 100644 --- a/pkg/fuzzer/prio_queue.go +++ b/pkg/fuzzer/prio_queue.go @@ -24,41 +24,28 @@ func (p priority) greaterThan(other priority) bool { type priorityQueue[T any] struct { impl priorityQueueImpl[T] - c *sync.Cond + mu sync.RWMutex } func makePriorityQueue[T any]() *priorityQueue[T] { - return &priorityQueue[T]{ - c: sync.NewCond(&sync.Mutex{}), - } + return &priorityQueue[T]{} } func (pq *priorityQueue[T]) Len() int { - pq.c.L.Lock() - defer pq.c.L.Unlock() + pq.mu.RLock() + defer pq.mu.RUnlock() return pq.impl.Len() } func (pq *priorityQueue[T]) push(item *priorityQueueItem[T]) { - pq.c.L.Lock() - defer pq.c.L.Unlock() + pq.mu.Lock() + defer pq.mu.Unlock() heap.Push(&pq.impl, item) - pq.c.Signal() -} - -// pop() blocks until there's input. -func (pq *priorityQueue[T]) pop() *priorityQueueItem[T] { - pq.c.L.Lock() - defer pq.c.L.Unlock() - for pq.impl.Len() == 0 { - pq.c.Wait() - } - return heap.Pop(&pq.impl).(*priorityQueueItem[T]) } func (pq *priorityQueue[T]) tryPop() *priorityQueueItem[T] { - pq.c.L.Lock() - defer pq.c.L.Unlock() + pq.mu.Lock() + defer pq.mu.Unlock() if len(pq.impl) == 0 { return nil } diff --git a/pkg/fuzzer/prio_queue_test.go b/pkg/fuzzer/prio_queue_test.go index b2abdb01b..df8b4e9b0 100644 --- a/pkg/fuzzer/prio_queue_test.go +++ b/pkg/fuzzer/prio_queue_test.go @@ -4,10 +4,10 @@ package fuzzer import ( - "sync" "testing" "github.com/stretchr/testify/assert" + "golang.org/x/sync/errgroup" ) func TestPriority(t *testing.T) { @@ -18,27 +18,40 @@ func TestPriority(t *testing.T) { func TestPrioQueueOrder(t *testing.T) { pq := makePriorityQueue[int]() + assert.Nil(t, pq.tryPop()) + pq.push(&priorityQueueItem[int]{value: 1, prio: priority{1}}) pq.push(&priorityQueueItem[int]{value: 3, prio: priority{3}}) pq.push(&priorityQueueItem[int]{value: 2, prio: priority{2}}) - assert.Equal(t, 3, pq.pop().value) - assert.Equal(t, 2, pq.pop().value) - assert.Equal(t, 1, pq.pop().value) + assert.Equal(t, 3, pq.tryPop().value) + assert.Equal(t, 2, pq.tryPop().value) + assert.Equal(t, 1, pq.tryPop().value) assert.Nil(t, pq.tryPop()) + assert.Zero(t, pq.Len()) } -func TestPrioQueueWait(t *testing.T) { - var wg sync.WaitGroup +func TestPrioQueueRace(t *testing.T) { + var eg errgroup.Group pq := makePriorityQueue[int]() - assert.Nil(t, pq.tryPop()) - - wg.Add(1) - go func() { - assert.Equal(t, 10, pq.pop().value) - wg.Done() - }() - pq.push(&priorityQueueItem[int]{value: 10, prio: priority{1}}) - wg.Wait() + // Two writers. + for writer := 0; writer < 2; writer++ { + eg.Go(func() error { + for i := 0; i < 1000; i++ { + pq.push(&priorityQueueItem[int]{value: 10, prio: priority{1}}) + } + return nil + }) + } + // Two readers. + for reader := 0; reader < 2; reader++ { + eg.Go(func() error { + for i := 0; i < 1000; i++ { + pq.tryPop() + } + return nil + }) + } + eg.Wait() } -- cgit mrf-deployment