-
Notifications
You must be signed in to change notification settings - Fork 0
/
queue.go
115 lines (92 loc) · 2.2 KB
/
queue.go
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
//Package queue provides a FIFO queue with mutex lock for safe read and write
//
//Queue uses linked list internal structure
package queue
import (
"errors"
"sync"
)
//Internal node for holding the value
//and the pointer to the next node
type node struct {
Value interface{} //The data
NextNode *node //Next node
}
//Queue is FIFO based queue with linked-list structure
type Queue struct {
head *node //Pointer to the first node
tail *node //Pointer to the last node
size int //Number of nodes in the queue
mu sync.RWMutex //Mutex lock for atomic operations
}
//Creates a new queue
func NewQueue() *Queue {
return &Queue{}
}
//Push add to the end of the queue
func (q *Queue) Push(i interface{}) {
//Lock it
q.mu.Lock()
//Create a new node a contaier for the value
newNode := node{i, nil}
//Check if the queue is empty or not
if q.head == nil {
//Empty so set the head pointer to the new node
q.head = &newNode
} else {
//Not empty direct the current last node
//to the new last node
q.tail.NextNode = &newNode
}
//And allways set the tail to the new last node
q.tail = &newNode
//Increase the size before return
q.size++
//Unlock it
q.mu.Unlock()
return
}
//Pop remove and return the oldest node in the queue.
//If the queue is empty error will contain "Queue is empty"
func (q *Queue) Pop() (i interface{}, err error) {
//Check if the queue is empty
if q.IsEmpty() {
return nil, errors.New("Queue is empty")
}
//Lock it
q.mu.Lock()
//Take out the headNode
var headNode = *q.head
//Check if we only got one item left in the queue
if q.head == q.tail {
//Then set the tail to nil
q.tail = nil
}
//Move the head pointer one step forward
q.head = q.head.NextNode
//Reduce the size before return
q.size--
//Unlock it
q.mu.Unlock()
return headNode.Value, nil
}
// The number of elements in the queue
func (q *Queue) Size() int {
//Lock it
q.mu.RLock()
//Get the data
size := q.size
//Unlock it
q.mu.RUnlock()
return size
}
// Returns true if there is elements in the queue, otherwise false
func (q *Queue) IsEmpty() bool {
//Lock it
q.mu.RLock()
//Get the data
empty := q.head == nil
//Unlock it
q.mu.RUnlock()
return empty
}