-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqueue.go
More file actions
196 lines (170 loc) Β· 4.36 KB
/
queue.go
File metadata and controls
196 lines (170 loc) Β· 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package arrayqueue
import (
"fmt"
"strings"
"github.com/forbearing/gst/ds/list/arraylist"
"github.com/forbearing/gst/ds/types"
)
// Queue represents a queue based on an array-backed list.
// This queue implements the FIFO (first-in, first-out) behavior.
type Queue[E any] struct {
list *arraylist.List[E]
cmp func(E, E) int
mu types.Locker
safe bool
}
// New creates and initializes a empty queue.
// The "cmp" function is used to compare elements for equality.
// Options can be provided to customize the queue's properties (e.g., thread safety).
func New[E any](cmp func(E, E) int, ops ...Option[E]) (*Queue[E], error) {
q := &Queue[E]{mu: types.FakeLocker{}, cmp: cmp}
var err error
for _, op := range ops {
if op == nil {
continue
}
if err = op(q); err != nil {
return nil, err
}
}
// internal list alway concurrent unsafe.
q.list, err = arraylist.New(cmp)
if err != nil {
return nil, err
}
return q, nil
}
// NewFromSlice creates and initializes a queue from the provided slice.
// The "cmp" function is used to compare elements for equality.
// Options can be provided to customize the queue's properties (e.g., thread safety).
func NewFromSlice[E any](cmp func(E, E) int, slice []E, ops ...Option[E]) (*Queue[E], error) {
q, err := New(cmp, ops...)
if err != nil {
return nil, err
}
if len(slice) > 0 {
q.list.Append(slice...)
}
return q, nil
}
// NewFromMapKeys creates and initializes a queue from the provided map keys.
// The "cmp" function is used to compare elements for equality.
// Options can be provided to customize the queue's properties (e.g., thread safety).
func NewFromMapKeys[K comparable, V any](cmp func(K, K) int, m map[K]V, ops ...Option[K]) (*Queue[K], error) {
q, err := New(cmp, ops...)
if err != nil {
return nil, err
}
if len(m) > 0 {
for k := range m {
q.list.Append(k)
}
}
return q, nil
}
// NewFromMapValues creates and initializes a queue from the provided map values.
// The "cmp" function is used to compare elements for equality.
// Options can be provided to customize the queue's properties (e.g., thread safety).
func NewFromMapValues[K comparable, V any](cmp func(V, V) int, m map[K]V, ops ...Option[V]) (*Queue[V], error) {
q, err := New(cmp, ops...)
if err != nil {
return nil, err
}
if len(m) > 0 {
for _, v := range m {
q.list.Append(v)
}
}
return q, nil
}
// Enqueue adds a element to the end of the queue.
func (q *Queue[E]) Enqueue(e E) {
if q.safe {
q.mu.Lock()
defer q.mu.Unlock()
}
q.list.Append(e)
}
// Dequeue removes first element of the queue.
// Returns zero value of element and false if queue is empty.
func (q *Queue[E]) Dequeue() (E, bool) {
if q.safe {
q.mu.Lock()
defer q.mu.Unlock()
}
e, ok := q.list.Get(0)
if ok {
q.list.RemoveAt(0)
}
return e, ok
}
// Peek returns first element of the queue without remove it.
// Returns zero value of element and false if queue is empty.
func (q *Queue[E]) Peek() (E, bool) {
if q.safe {
q.mu.RLock()
defer q.mu.RUnlock()
}
return q.list.Get(0)
}
// IsEmpty reports whether the queue has no element.
func (q *Queue[E]) IsEmpty() bool {
if q.safe {
q.mu.RLock()
defer q.mu.RUnlock()
}
return q.list.IsEmpty()
}
// Len returns the number of elements currently in the queue.
func (q *Queue[E]) Len() int {
if q.safe {
q.mu.RLock()
defer q.mu.RUnlock()
}
return q.list.Len()
}
// Values returns all elements in the queue in FIFO(first-in, first-out) order.
func (q *Queue[E]) Values() []E {
if q.safe {
q.mu.RLock()
defer q.mu.RUnlock()
}
return q.list.Values()
}
// Clear removes all elements from the queue.
func (q *Queue[E]) Clear() {
if q.safe {
q.mu.Lock()
defer q.mu.Unlock()
}
q.list.Clear()
}
// Clone returns a deep copy of the queue.
func (q *Queue[E]) Clone() *Queue[E] {
if q.safe {
q.mu.RLock()
defer q.mu.RUnlock()
}
clone, _ := NewFromSlice(q.cmp, q.list.Values(), q.options()...)
return clone
}
func (q *Queue[E]) options() []Option[E] {
ops := make([]Option[E], 0)
if q.safe {
ops = append(ops, WithSafe[E]())
}
return ops
}
// String returns a string representation of the queue.
func (q *Queue[E]) String() string {
if q.safe {
q.mu.RLock()
defer q.mu.RUnlock()
}
items := make([]string, 0, q.list.Len())
q.list.Range(func(e E) bool {
items = append(items, fmt.Sprintf("%v", e))
return true
})
return fmt.Sprintf("queue:{%s}", strings.Join(items, ", "))
}