gqueue

package
v0.9.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2025 License: MIT Imports: 4 Imported by: 0

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

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>
}

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
}

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
}

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

func NewRingQueue[T any](capacity int, safe ...bool) *RingQueue[T]

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

func (q *RingQueue[T]) Cap() int

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

func (q *RingQueue[T]) IsEmpty() bool

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

func (q *RingQueue[T]) Len() int

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

func (q *RingQueue[T]) Peek() (x T, ok bool)

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

func (q *RingQueue[T]) Pop() (x T, ok bool)

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

func (q *RingQueue[T]) PopMulti(numberOfItems int) []T

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL