11package queue
22
3+ import (
4+ "sync"
5+ )
6+
37var _ Queue [any ] = (* Linked [any ])(nil )
48
59// node is an individual element of the linked list.
@@ -10,13 +14,14 @@ type node[T any] struct {
1014
1115// Linked represents a data structure representing a queue that uses a
1216// linked list for its internal storage.
13- // ! The Linked Queue is not thread safe.
1417type Linked [T comparable ] struct {
1518 head * node [T ] // first node of the queue.
1619 tail * node [T ] // last node of the queue.
1720 size int // number of elements in the queue.
1821 // nolint: revive
1922 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
2025}
2126
2227// NewLinked creates a new Linked containing the given elements.
@@ -31,59 +36,76 @@ func NewLinked[T comparable](elements []T) *Linked[T] {
3136 copy (queue .initialElements , elements )
3237
3338 for _ , element := range elements {
34- _ = queue .Offer (element )
39+ _ = queue .offer (element )
3540 }
3641
3742 return queue
3843}
3944
4045// 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 () {
4351 return elem , ErrNoElementsAvailable
4452 }
4553
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 --
4957
50- if q . IsEmpty () {
51- q .tail = nil
58+ if lq . isEmpty () {
59+ lq .tail = nil
5260 }
5361
5462 return value , nil
5563}
5664
5765// 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 {
5975 newNode := & node [T ]{value : value }
6076
61- if q . IsEmpty () {
62- q .head = newNode
77+ if lq . isEmpty () {
78+ lq .head = newNode
6379 } else {
64- q .tail .next = newNode
80+ lq .tail .next = newNode
6581 }
6682
67- q .tail = newNode
68- q .size ++
83+ lq .tail = newNode
84+ lq .size ++
6985
7086 return nil
7187}
7288
7389// 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
7897
79- for _ , element := range q .initialElements {
80- _ = q . Offer (element )
98+ for _ , element := range lq .initialElements {
99+ _ = lq . offer (element )
81100 }
82101}
83102
84103// 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
87109 for current != nil {
88110 if current .value == value {
89111 return true
@@ -96,30 +118,44 @@ func (q *Linked[T]) Contains(value T) bool {
96118}
97119
98120// 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 () {
101126 return elem , ErrNoElementsAvailable
102127 }
103128
104- return q .head .value , nil
129+ return lq .head .value , nil
105130}
106131
107132// 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
110138}
111139
112140// 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
115151}
116152
117153// Iterator returns a channel that will be filled with the elements.
118154// It removes the elements from the queue.
119- func (q * Linked [T ]) Iterator () <- chan T {
155+ func (lq * Linked [T ]) Iterator () <- chan T {
120156 ch := make (chan T )
121157
122- elems := q .Clear ()
158+ elems := lq .Clear ()
123159
124160 go func () {
125161 for _ , e := range elems {
@@ -133,20 +169,23 @@ func (q *Linked[T]) Iterator() <-chan T {
133169}
134170
135171// 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 )
138177
139- current := q .head
178+ current := lq .head
140179 for current != nil {
141180 elements = append (elements , current .value )
142181 next := current .next
143182 current = next
144183 }
145184
146185 // 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
150189
151190 return elements
152191}
0 commit comments