forked from hyperledger-archives/fabric
/
queue.go
106 lines (87 loc) · 2.32 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
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package util
import "sync"
// Queue is a classic implmentation of a FIFO queue object
type Queue struct {
head *element
tail *element
count int
lock *sync.Mutex
}
// Element is a single linked list with a data field containing any data
// structure from the caller
type element struct {
data interface{}
next *element
}
// NewQueue is a constructor returning a Queue object
func NewQueue() *Queue {
q := &Queue{}
q.lock = &sync.Mutex{}
return q
}
// Size returns the number of elements on the queue
func (q *Queue) Size() int {
q.lock.Lock()
defer q.lock.Unlock()
return q.count
}
// Push appends an item on the queue
// @param item - any application data
func (q *Queue) Push(item interface{}) {
q.lock.Lock()
defer q.lock.Unlock()
element := &element{data: item}
// Move tail along where t.next points the new element
if q.tail == nil {
q.tail = element
q.head = element
} else {
q.tail.next = element
q.tail = element
}
q.count++
}
// Pop returns the data item at the head of the queue
// Example e := q.Pop().(T) -- cast e to type T
func (q *Queue) Pop() interface{} {
q.lock.Lock()
defer q.lock.Unlock()
if q.head == nil {
return nil
}
// Move head to the next elment
element := q.head
q.head = element.next
// If nothing left on the queue, nilify for garbage collection
if q.head == nil {
q.tail = nil
}
q.count--
return element.data
}
// Peek returns the data at the head of the queue
func (q *Queue) Peek() interface{} {
q.lock.Lock()
defer q.lock.Unlock()
element := q.head
if element == nil {
return nil
}
return element.data
}