Documentation
¶
Overview ¶
Package gqueue provides dynamic/static concurrent-safe queue.
Features:
1. FIFO queue(data -> list -> chan);
2. Fast creation and initialization;
3. Support dynamic queue size(unlimited queue size);
4. Blocking when reading data from queue;
Index ¶
- type BlockingQueue
- type RingQueue
- func (q *RingQueue[T]) Cap() int
- func (q *RingQueue[T]) Clear()
- func (q *RingQueue[T]) IsEmpty() bool
- func (q *RingQueue[T]) Len() int
- func (q *RingQueue[T]) MustPeek() T
- func (q *RingQueue[T]) MustPop() T
- func (q *RingQueue[T]) Peek() (x T, ok bool)
- func (q *RingQueue[T]) Pop() (x T, ok bool)
- func (q *RingQueue[T]) PopAll() []T
- func (q *RingQueue[T]) PopMulti(numberOfItems int) []T
- func (q *RingQueue[T]) Push(x T)
- func (q *RingQueue[T]) Snapshot(dst []T) []T
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BlockingQueue ¶ added in v0.9.7
type BlockingQueue[T any] struct { C chan T // Underlying channel for data reading. // contains filtered or unexported fields }
BlockingQueue is a concurrent-safe queue built on doubly linked list and channel.
func New ¶
func New[T any](limit ...int) *BlockingQueue[T]
New returns an empty queue object. Optional parameter `limit` is used to limit the size of the queue, which is unlimited in default. When `limit` is given, the queue will be static and high performance which is any with stdlib channel.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/wesleywu/gcontainer/gqueue"
"github.com/wesleywu/gcontainer/gtimer"
)
func main() {
n := 10
q := gqueue.New[int](100)
// Producer
for i := 0; i < n; i++ {
q.Push(i)
}
// Close the queue in three seconds.
gtimer.SetTimeout(context.Background(), time.Second*3, func(ctx context.Context) error {
q.Close()
return nil
})
// The consumer constantly reads the queue data.
// If there is no data in the queue, it will block.
// The queue is read using the queue.C property exposed
// by the queue object and the selectIO multiplexing syntax
// example:
// for {
// select {
// case v := <-queue.C:
// if v != nil {
// fmt.Println(v)
// } else {
// return
// }
// }
// }
for {
v, ok := q.Pop()
if ok {
fmt.Print(v)
} else {
break
}
}
}
Output: 0123456789
func (*BlockingQueue[T]) Close ¶ added in v0.9.7
func (q *BlockingQueue[T]) Close()
Close closes the queue. Notice: It would notify all goroutines return immediately, which are being blocked reading using Pop method.
Example ¶
package main
import (
"fmt"
"time"
"github.com/wesleywu/gcontainer/gqueue"
)
func main() {
q := gqueue.New[int]()
for i := 0; i < 10; i++ {
q.Push(i)
}
time.Sleep(time.Millisecond)
q.Close()
fmt.Println(q.Len())
fmt.Println(q.Pop())
// May Output:
// 0
// <nil>
}
Output:
func (*BlockingQueue[T]) Len ¶ added in v0.9.7
func (q *BlockingQueue[T]) Len() (length int64)
Len returns the length of the queue. Note that the result might not be accurate if using unlimited queue size as there's an asynchronous channel reading the list constantly.
Example ¶
package main
import (
"fmt"
"github.com/wesleywu/gcontainer/gqueue"
)
func main() {
q := gqueue.New[int]()
q.Push(1)
q.Push(2)
fmt.Println(q.Len())
// May Output:
// 2
}
Output:
func (*BlockingQueue[T]) MustPop ¶ added in v0.9.7
func (q *BlockingQueue[T]) MustPop() T
MustPop pops an item from the queue in FIFO way. Note that it would return empty value of T or nil if T is a pointer, when Pop is called after the queue is closed.
Example ¶
package main
import (
"fmt"
"github.com/wesleywu/gcontainer/gqueue"
)
type exampleQueueItem struct {
index int
}
func main() {
q := gqueue.New[*exampleQueueItem]()
for i := 0; i < 10; i++ {
q.Push(&exampleQueueItem{index: i})
}
fmt.Println(q.MustPop())
fmt.Println(q.MustPop())
fmt.Println(q.MustPop())
q.Close()
fmt.Println(q.MustPop())
}
Output: &{0} &{1} &{2} <nil>
func (*BlockingQueue[T]) Pop ¶ added in v0.9.7
func (q *BlockingQueue[T]) Pop() (result T, ok bool)
Pop pops an item from the queue in FIFO way, and a bool value indicating whether the channel is still open.
Example ¶
package main
import (
"fmt"
"github.com/wesleywu/gcontainer/gqueue"
)
func main() {
q := gqueue.New[int]()
for i := 0; i < 10; i++ {
q.Push(i)
}
v, ok := q.Pop()
fmt.Println(v, ok)
v, ok = q.Pop()
fmt.Println(v, ok)
v, ok = q.Pop()
fmt.Println(v, ok)
q.Close()
v, ok = q.Pop()
fmt.Println(v, ok)
}
Output: 0 true 1 true 2 true 0 false
func (*BlockingQueue[T]) Push ¶ added in v0.9.7
func (q *BlockingQueue[T]) Push(v T)
Push pushes the data `v` into the queue. Note that it would panic if Push is called after the queue is closed.
Example ¶
package main
import (
"fmt"
"github.com/wesleywu/gcontainer/gqueue"
)
func main() {
q := gqueue.New[int]()
for i := 0; i < 10; i++ {
q.Push(i)
}
fmt.Println(q.MustPop())
fmt.Println(q.MustPop())
fmt.Println(q.MustPop())
}
Output: 0 1 2
func (*BlockingQueue[T]) Size ¶ added in v0.9.7
func (q *BlockingQueue[T]) Size() int64
Size is alias of Len. Deprecated: use Len instead.
Example ¶
package main
import (
"fmt"
"github.com/wesleywu/gcontainer/gqueue"
)
func main() {
q := gqueue.New[int]()
q.Push(1)
q.Push(2)
// Size is alias of Len.
fmt.Println(q.Size())
// May Output:
// 2
}
Output:
type RingQueue ¶ added in v0.9.7
type RingQueue[T any] struct { // contains filtered or unexported fields }
RingQueue is a FIFO queue backed by a ring buffer, designed for minimal allocation. The zero value for RingQueue is an empty queue ready to use, though not thread-safe.
RingQueue is thread-safe for concurrent use by calling NewRingQueue with safe = true.
func NewRingQueue ¶ added in v0.9.7
NewRingQueue returns a new queue with the given capacity. If capacity is zero, the queue is initialized with a default capacity. If safe is true, the queue is thread-safe for concurrent use
The capacity defines the leeway for bursts of pushes before the queue needs to grow.
func (*RingQueue[T]) Cap ¶ added in v0.9.7
Cap returns the current capacity of items.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) Clear ¶ added in v0.9.7
func (q *RingQueue[T]) Clear()
Clear removes all items from the queue. It does not adjust its internal capacity.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) IsEmpty ¶ added in v0.9.7
IsEmpty returns true if the queue is empty.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) Len ¶ added in v0.9.7
Len returns the number of items in the queue.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) MustPeek ¶ added in v0.9.7
func (q *RingQueue[T]) MustPeek() T
MustPeek returns the item at the front of the queue without removing it. It returns empty value of T if the queue is empty.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) MustPop ¶ added in v0.9.7
func (q *RingQueue[T]) MustPop() T
MustPop removes and returns the item at the front of the queue. It returns empty value of T if the queue is empty.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) Peek ¶ added in v0.9.7
Peek returns the item at the front of the queue. It returns false if the queue is empty. Otherwise, it returns true and the item.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) Pop ¶ added in v0.9.7
Pop removes and returns the item at the front of the queue. It returns false if the queue is empty. Otherwise, it returns true and the item.
This is an O(1) operation and does not allocate.
func (*RingQueue[T]) PopAll ¶ added in v0.9.7
func (q *RingQueue[T]) PopAll() []T
PopAll removes returns all items from the front to the tail of the queue. It returns empty slice if the queue is empty. Otherwise, it returns the popped items.
This is an O(n) operation
func (*RingQueue[T]) PopMulti ¶ added in v0.9.7
PopMulti removes and returns specified number of items at the front of the queue. It returns empty slice if the queue is empty. Otherwise, it returns the popped items.
This is an O(n) operation
func (*RingQueue[T]) Push ¶ added in v0.9.7
func (q *RingQueue[T]) Push(x T)
Push adds x to the back of the queue.
This operation is O(n) in the worst case if the queue needs to grow. However, for target use cases, it's amortized O(1). See package documentation for details.
func (*RingQueue[T]) Snapshot ¶ added in v0.9.7
func (q *RingQueue[T]) Snapshot(dst []T) []T
Snapshot appends the contents of the queue to dst and returns the result. Use dst to avoid allocations when you know the capacity of the queue
dst := make([]T, 0, q.Len()) dst = q.Snapshot(dst)
Pass nil to let the function allocate a new slice.
q.Snapshot(nil) // allocates a new slice
The returned slice is a copy of the internal buffer and is safe to modify.