Skip to content

Commit 49d8c10

Browse files
committed
docs(readme): polish intro, quickstart, bottom matter, and example consistency
Top matter - Replace three-sentence intro with a one-line tagline. - Add a Features bullet list. - Surface pkg.go.dev as a prominent body link. New sections - Quick start snippet (using NewLinked) between Import and Choosing. - Contributing, Security, License at the bottom, each linking to the file that already exists in the repo. - Maintainer callout. Per-queue examples - Linked Queue example: variable was named `circularQueue` (copy-paste from the Circular section) — renamed to `linkedQueue`. - Priority Queue example: fix misaligned closing paren; switch "comparator function" to "less function" to match the code. - Blocking Queue example: use Printf instead of Println for the elem output line — Println inserts a space so the old `elem: 2` comment was actually wrong (would print `elem: 2`). - Normalise indentation of all code samples to tabs. Nits - Drop trailing whitespace on a couple of lines. - Drop trailing space in the "## Benchmarks " heading. - Remove the awkward "Benchmarks and Example tests can be found…" line. - Quick-start `// 1, 2, 3, 4` comment moved above the loop and rephrased so it doesn't look like the output of a single Println. - Benchmark-shape sentence now covers Priority and Delay. No code changes.
1 parent 3472c91 commit 49d8c10

File tree

1 file changed

+123
-76
lines changed

1 file changed

+123
-76
lines changed

README.md

Lines changed: 123 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@
1717

1818
---
1919

20-
The `queue` package provides thread-safe generic implementations in Go for the following data structures: `BlockingQueue`, `PriorityQueue`, `CircularQueue`, `Linked Queue` and `DelayQueue`.
20+
Thread-safe, generic FIFO, priority, circular, linked, and delay queues for Go.
2121

22-
A queue is a sequence of entities that is open at both ends where the elements are
23-
added (enqueued) to the tail (back) of the queue and removed (dequeued) from the head (front) of the queue.
22+
## Features
2423

25-
The implementations are designed to be easy-to-use and provide a consistent API, satisfying the `Queue` interface provided by this package. .
24+
- Five queue flavours behind one `Queue[T comparable]` interface — swap implementations without changing call sites.
25+
- Generic types with no reflection; zero third-party dependencies.
26+
- Steady-state zero-alloc reads on every queue and zero-alloc offer/get on `Circular`, `Linked`, `Priority`, and `Delay`.
27+
- Blocking variants (`OfferWait`, `GetWait`, `PeekWait`) for producer/consumer workloads.
28+
- `Delay` queue for timers, retry scheduling, and TTL expiry.
29+
- 100% test coverage and race-tested in CI.
2630

27-
Benchmarks and Example tests can be found in this package.
31+
Full API reference at **[pkg.go.dev/github.com/adrianbrad/queue](https://pkg.go.dev/github.com/adrianbrad/queue)**.
2832

2933
<!-- TOC -->
3034
* [queue](#queue)
35+
* [Features](#features)
3136
* [Installation](#installation)
3237
* [Import](#import)
38+
* [Quick start](#quick-start)
3339
* [Choosing a queue](#choosing-a-queue)
3440
* [Usage](#usage)
3541
* [Queue Interface](#queue-interface)
@@ -38,7 +44,10 @@ Benchmarks and Example tests can be found in this package.
3844
* [Circular Queue](#circular-queue)
3945
* [Linked Queue](#linked-queue)
4046
* [Delay Queue](#delay-queue)
41-
* [Benchmarks](#benchmarks-)
47+
* [Benchmarks](#benchmarks)
48+
* [Contributing](#contributing)
49+
* [Security](#security)
50+
* [License](#license)
4251
<!-- TOC -->
4352

4453
## Installation
@@ -55,6 +64,32 @@ To use this package in your project, you can import it as follows:
5564
import "github.com/adrianbrad/queue"
5665
```
5766

67+
## Quick start
68+
69+
```go
70+
package main
71+
72+
import (
73+
"fmt"
74+
75+
"github.com/adrianbrad/queue"
76+
)
77+
78+
func main() {
79+
q := queue.NewLinked([]int{1, 2, 3})
80+
81+
_ = q.Offer(4)
82+
83+
// prints 1, then 2, then 3, then 4 (one per iteration)
84+
for !q.IsEmpty() {
85+
v, _ := q.Get()
86+
fmt.Println(v)
87+
}
88+
}
89+
```
90+
91+
Every implementation satisfies the same `Queue[T comparable]` interface — pick a different constructor (`NewBlocking`, `NewPriority`, `NewCircular`, `NewDelay`) without changing the call sites.
92+
5893
## Choosing a queue
5994

6095
| Queue | Ordering | Capacity | Blocks? | Pick this when… |
@@ -105,7 +140,7 @@ type Queue[T comparable] interface {
105140

106141
Blocking queue is a FIFO ordered data structure. Both blocking and non-blocking methods are implemented.
107142
Blocking methods wait for the queue to have available items when dequeuing, and wait for a slot to become available in case the queue is full when enqueuing.
108-
The non-blocking methods return an error if an element cannot be added or removed.
143+
The non-blocking methods return an error if an element cannot be added or removed.
109144
Implemented using sync.Cond from the standard library.
110145

111146
```go
@@ -140,14 +175,14 @@ func main() {
140175
// handle err
141176
}
142177

143-
fmt.Println("elem: ", elem) // elem: 2
178+
fmt.Printf("elem: %d\n", elem) // elem: 2
144179
}
145180
```
146181

147182
### Priority Queue
148183

149-
Priority Queue is a data structure where the order of the elements is given by a comparator function provided at construction.
150-
Implemented using container/heap standard library package.
184+
Priority Queue is a data structure where the order of the elements is given by a less function provided at construction.
185+
Implemented over an internal min-heap.
151186

152187
```go
153188
package main
@@ -162,9 +197,9 @@ func main() {
162197
elems := []int{2, 3, 4}
163198

164199
priorityQueue := queue.NewPriority(
165-
elems,
200+
elems,
166201
func(elem, otherElem int) bool { return elem < otherElem },
167-
)
202+
)
168203

169204
containsTwo := priorityQueue.Contains(2)
170205
fmt.Println(containsTwo) // true
@@ -204,35 +239,35 @@ then the next element to be removed from the queue will be the element at index
204239
package main
205240

206241
import (
207-
"fmt"
242+
"fmt"
208243

209-
"github.com/adrianbrad/queue"
244+
"github.com/adrianbrad/queue"
210245
)
211246

212247
func main() {
213-
elems := []int{2, 3, 4}
248+
elems := []int{2, 3, 4}
214249

215-
circularQueue := queue.NewCircular(elems, 3)
250+
circularQueue := queue.NewCircular(elems, 3)
216251

217-
containsTwo := circularQueue.Contains(2)
218-
fmt.Println(containsTwo) // true
252+
containsTwo := circularQueue.Contains(2)
253+
fmt.Println(containsTwo) // true
219254

220-
size := circularQueue.Size()
221-
fmt.Println(size) // 3
255+
size := circularQueue.Size()
256+
fmt.Println(size) // 3
222257

223-
empty := circularQueue.IsEmpty()
224-
fmt.Println(empty) // false
258+
empty := circularQueue.IsEmpty()
259+
fmt.Println(empty) // false
225260

226-
if err := circularQueue.Offer(1); err != nil {
227-
// handle err
228-
}
261+
if err := circularQueue.Offer(1); err != nil {
262+
// handle err
263+
}
229264

230-
elem, err := circularQueue.Get()
231-
if err != nil {
232-
// handle err
233-
}
265+
elem, err := circularQueue.Get()
266+
if err != nil {
267+
// handle err
268+
}
234269

235-
fmt.Printf("elem: %d\n", elem) // elem: 1
270+
fmt.Printf("elem: %d\n", elem) // elem: 1
236271
}
237272
```
238273

@@ -247,35 +282,35 @@ without the need for traversal.
247282
package main
248283

249284
import (
250-
"fmt"
285+
"fmt"
251286

252-
"github.com/adrianbrad/queue"
287+
"github.com/adrianbrad/queue"
253288
)
254289

255290
func main() {
256-
elems := []int{2, 3, 4}
291+
elems := []int{2, 3, 4}
257292

258-
circularQueue := queue.NewLinked(elems)
293+
linkedQueue := queue.NewLinked(elems)
259294

260-
containsTwo := circularQueue.Contains(2)
261-
fmt.Println(containsTwo) // true
295+
containsTwo := linkedQueue.Contains(2)
296+
fmt.Println(containsTwo) // true
262297

263-
size := circularQueue.Size()
264-
fmt.Println(size) // 3
298+
size := linkedQueue.Size()
299+
fmt.Println(size) // 3
265300

266-
empty := circularQueue.IsEmpty()
267-
fmt.Println(empty) // false
301+
empty := linkedQueue.IsEmpty()
302+
fmt.Println(empty) // false
268303

269-
if err := circularQueue.Offer(1); err != nil {
270-
// handle err
271-
}
304+
if err := linkedQueue.Offer(1); err != nil {
305+
// handle err
306+
}
272307

273-
elem, err := circularQueue.Get()
274-
if err != nil {
275-
// handle err
276-
}
308+
elem, err := linkedQueue.Get()
309+
if err != nil {
310+
// handle err
311+
}
277312

278-
fmt.Printf("elem: %d\n", elem) // elem: 2
313+
fmt.Printf("elem: %d\n", elem) // elem: 2
279314
}
280315
```
281316

@@ -287,45 +322,45 @@ A `Delay` queue is a priority queue where each element becomes dequeuable at a d
287322
package main
288323

289324
import (
290-
"fmt"
291-
"time"
325+
"fmt"
326+
"time"
292327

293-
"github.com/adrianbrad/queue"
328+
"github.com/adrianbrad/queue"
294329
)
295330

296331
type task struct {
297-
id int
298-
runAt time.Time
332+
id int
333+
runAt time.Time
299334
}
300335

301336
func main() {
302-
now := time.Now()
303-
304-
delayQueue := queue.NewDelay(
305-
[]task{
306-
{id: 1, runAt: now.Add(20 * time.Millisecond)},
307-
{id: 2, runAt: now.Add(5 * time.Millisecond)},
308-
},
309-
func(t task) time.Time { return t.runAt },
310-
)
311-
312-
size := delayQueue.Size()
313-
fmt.Println(size) // 2
314-
315-
// Non-blocking: not due yet.
316-
if _, err := delayQueue.Get(); err != nil {
317-
// err == queue.ErrNoElementsAvailable
318-
}
319-
320-
// Blocking: returns as soon as the head's deadline passes.
321-
next := delayQueue.GetWait()
322-
fmt.Printf("next: %d\n", next.id) // next: 2
337+
now := time.Now()
338+
339+
delayQueue := queue.NewDelay(
340+
[]task{
341+
{id: 1, runAt: now.Add(20 * time.Millisecond)},
342+
{id: 2, runAt: now.Add(5 * time.Millisecond)},
343+
},
344+
func(t task) time.Time { return t.runAt },
345+
)
346+
347+
size := delayQueue.Size()
348+
fmt.Println(size) // 2
349+
350+
// Non-blocking: not due yet.
351+
if _, err := delayQueue.Get(); err != nil {
352+
// err == queue.ErrNoElementsAvailable
353+
}
354+
355+
// Blocking: returns as soon as the head's deadline passes.
356+
next := delayQueue.GetWait()
357+
fmt.Printf("next: %d\n", next.id) // next: 2
323358
}
324359
```
325360

326-
## Benchmarks
361+
## Benchmarks
327362

328-
Run locally with `go test -bench=. -benchmem -benchtime=3s -count=3`. Reported numbers are per-operation timings and allocations; absolute values vary by hardware, but the shape (zero-alloc reads everywhere, zero-alloc offer/get for Circular and Linked) should be stable.
363+
Run locally with `go test -bench=. -benchmem -benchtime=3s -count=3`. Reported numbers are per-operation timings and allocations; absolute values vary by hardware, but the shape (zero-alloc reads everywhere, zero-alloc offer/get for Circular, Linked, Priority, and Delay) should be stable.
329364

330365
```text
331366
BenchmarkBlockingQueue/Peek 3.8 ns/op 0 B/op 0 allocs/op
@@ -344,3 +379,15 @@ BenchmarkDelayQueue/Peek 4.1 ns/op 0 B/op 0 allocs/o
344379
BenchmarkDelayQueue/Get_Offer 52.4 ns/op 0 B/op 0 allocs/op
345380
BenchmarkDelayQueue/Offer 63.5 ns/op 315 B/op 0 allocs/op
346381
```
382+
383+
## Contributing
384+
385+
PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow, coding conventions, and the 100% coverage requirement. Ask questions by opening a GitHub issue.
386+
387+
## Security
388+
389+
Please report security issues privately following [SECURITY.md](SECURITY.md) rather than opening a public issue.
390+
391+
## License
392+
393+
MIT — see [LICENSE](LICENSE). Maintained by [@adrianbrad](https://github.com/adrianbrad).

0 commit comments

Comments
 (0)