1
1
package queue
2
2
3
+ import (
4
+ "sync"
5
+ )
6
+
3
7
var _ Queue [any ] = (* Linked [any ])(nil )
4
8
5
9
// node is an individual element of the linked list.
@@ -10,13 +14,14 @@ type node[T any] struct {
10
14
11
15
// Linked represents a data structure representing a queue that uses a
12
16
// linked list for its internal storage.
13
- // ! The Linked Queue is not thread safe.
14
17
type Linked [T comparable ] struct {
15
18
head * node [T ] // first node of the queue.
16
19
tail * node [T ] // last node of the queue.
17
20
size int // number of elements in the queue.
18
21
// nolint: revive
19
22
initialElements []T // initial elements with which the queue was created, allowing for a reset to its original state if needed.
23
+ // synchronization
24
+ lock sync.RWMutex
20
25
}
21
26
22
27
// NewLinked creates a new Linked containing the given elements.
@@ -31,59 +36,76 @@ func NewLinked[T comparable](elements []T) *Linked[T] {
31
36
copy (queue .initialElements , elements )
32
37
33
38
for _ , element := range elements {
34
- _ = queue .Offer (element )
39
+ _ = queue .offer (element )
35
40
}
36
41
37
42
return queue
38
43
}
39
44
40
45
// Get retrieves and removes the head of the queue.
41
- func (q * Linked [T ]) Get () (elem T , _ error ) {
42
- if q .IsEmpty () {
46
+ func (lq * Linked [T ]) Get () (elem T , _ error ) {
47
+ lq .lock .Lock ()
48
+ defer lq .lock .Unlock ()
49
+
50
+ if lq .isEmpty () {
43
51
return elem , ErrNoElementsAvailable
44
52
}
45
53
46
- value := q .head .value
47
- q .head = q .head .next
48
- q .size --
54
+ value := lq .head .value
55
+ lq .head = lq .head .next
56
+ lq .size --
49
57
50
- if q . IsEmpty () {
51
- q .tail = nil
58
+ if lq . isEmpty () {
59
+ lq .tail = nil
52
60
}
53
61
54
62
return value , nil
55
63
}
56
64
57
65
// Offer inserts the element into the queue.
58
- func (q * Linked [T ]) Offer (value T ) error {
66
+ func (lq * Linked [T ]) Offer (value T ) error {
67
+ lq .lock .Lock ()
68
+ defer lq .lock .Unlock ()
69
+
70
+ return lq .offer (value )
71
+ }
72
+
73
+ // offer inserts the element into the queue.
74
+ func (lq * Linked [T ]) offer (value T ) error {
59
75
newNode := & node [T ]{value : value }
60
76
61
- if q . IsEmpty () {
62
- q .head = newNode
77
+ if lq . isEmpty () {
78
+ lq .head = newNode
63
79
} else {
64
- q .tail .next = newNode
80
+ lq .tail .next = newNode
65
81
}
66
82
67
- q .tail = newNode
68
- q .size ++
83
+ lq .tail = newNode
84
+ lq .size ++
69
85
70
86
return nil
71
87
}
72
88
73
89
// Reset sets the queue to its initial state.
74
- func (q * Linked [T ]) Reset () {
75
- q .head = nil
76
- q .tail = nil
77
- q .size = 0
90
+ func (lq * Linked [T ]) Reset () {
91
+ lq .lock .Lock ()
92
+ defer lq .lock .Unlock ()
93
+
94
+ lq .head = nil
95
+ lq .tail = nil
96
+ lq .size = 0
78
97
79
- for _ , element := range q .initialElements {
80
- _ = q . Offer (element )
98
+ for _ , element := range lq .initialElements {
99
+ _ = lq . offer (element )
81
100
}
82
101
}
83
102
84
103
// Contains returns true if the queue contains the element.
85
- func (q * Linked [T ]) Contains (value T ) bool {
86
- current := q .head
104
+ func (lq * Linked [T ]) Contains (value T ) bool {
105
+ lq .lock .RLock ()
106
+ defer lq .lock .RUnlock ()
107
+
108
+ current := lq .head
87
109
for current != nil {
88
110
if current .value == value {
89
111
return true
@@ -96,30 +118,44 @@ func (q *Linked[T]) Contains(value T) bool {
96
118
}
97
119
98
120
// Peek retrieves but does not remove the head of the queue.
99
- func (q * Linked [T ]) Peek () (elem T , _ error ) {
100
- if q .IsEmpty () {
121
+ func (lq * Linked [T ]) Peek () (elem T , _ error ) {
122
+ lq .lock .RLock ()
123
+ defer lq .lock .RUnlock ()
124
+
125
+ if lq .isEmpty () {
101
126
return elem , ErrNoElementsAvailable
102
127
}
103
128
104
- return q .head .value , nil
129
+ return lq .head .value , nil
105
130
}
106
131
107
132
// Size returns the number of elements in the queue.
108
- func (q * Linked [T ]) Size () int {
109
- return q .size
133
+ func (lq * Linked [T ]) Size () int {
134
+ lq .lock .RLock ()
135
+ defer lq .lock .RUnlock ()
136
+
137
+ return lq .size
110
138
}
111
139
112
140
// IsEmpty returns true if the queue is empty, false otherwise.
113
- func (q * Linked [T ]) IsEmpty () bool {
114
- return q .size == 0
141
+ func (lq * Linked [T ]) IsEmpty () bool {
142
+ lq .lock .RLock ()
143
+ defer lq .lock .RUnlock ()
144
+
145
+ return lq .isEmpty ()
146
+ }
147
+
148
+ // IsEmpty returns true if the queue is empty, false otherwise.
149
+ func (lq * Linked [T ]) isEmpty () bool {
150
+ return lq .size == 0
115
151
}
116
152
117
153
// Iterator returns a channel that will be filled with the elements.
118
154
// It removes the elements from the queue.
119
- func (q * Linked [T ]) Iterator () <- chan T {
155
+ func (lq * Linked [T ]) Iterator () <- chan T {
120
156
ch := make (chan T )
121
157
122
- elems := q .Clear ()
158
+ elems := lq .Clear ()
123
159
124
160
go func () {
125
161
for _ , e := range elems {
@@ -133,20 +169,23 @@ func (q *Linked[T]) Iterator() <-chan T {
133
169
}
134
170
135
171
// Clear removes and returns all elements from the queue.
136
- func (q * Linked [T ]) Clear () []T {
137
- elements := make ([]T , 0 , q .size )
172
+ func (lq * Linked [T ]) Clear () []T {
173
+ lq .lock .Lock ()
174
+ defer lq .lock .Unlock ()
175
+
176
+ elements := make ([]T , 0 , lq .size )
138
177
139
- current := q .head
178
+ current := lq .head
140
179
for current != nil {
141
180
elements = append (elements , current .value )
142
181
next := current .next
143
182
current = next
144
183
}
145
184
146
185
// Clear the queue
147
- q .head = nil
148
- q .tail = nil
149
- q .size = 0
186
+ lq .head = nil
187
+ lq .tail = nil
188
+ lq .size = 0
150
189
151
190
return elements
152
191
}
0 commit comments