-
Notifications
You must be signed in to change notification settings - Fork 10
/
queue.go
142 lines (120 loc) · 3.23 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
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
package common
import "sync"
// потоко-безопасная очередь
type Queue struct {
// флаг, сигнализирующий, что очередь пуста
empty bool
// элементы очереди
items []interface{}
// семафор
mutex *sync.Mutex
}
// создает новую очередь
func NewQueue() *Queue {
return &Queue{
empty: true,
items: make([]interface{}, 0),
mutex: new(sync.Mutex),
}
}
// добавляет элемент в конец очереди
func (q *Queue) Push(item interface{}) {
q.mutex.Lock()
if q.empty {
q.empty = false
}
q.items = append(q.items, item)
q.mutex.Unlock()
}
// достает первый элемент из очереди
func (q *Queue) Pop() interface{} {
var item interface{}
q.mutex.Lock()
if !q.empty {
oldItems := q.items
oldItemsLen := len(oldItems)
if oldItemsLen > 0 {
item = oldItems[oldItemsLen-1]
q.items = oldItems[0 : oldItemsLen-1]
} else {
q.empty = true
}
}
q.mutex.Unlock()
return item
}
// сигнализирует, что очередь пуста
func (q *Queue) Empty() bool {
var empty bool
q.mutex.Lock()
empty = q.empty
q.mutex.Unlock()
return empty
}
// возвращает длину очереди
func (q *Queue) Len() int {
var itemsLen int
q.mutex.Lock()
itemsLen = len(q.items)
q.mutex.Unlock()
return itemsLen
}
// статус очереди
type queueStatus int
const (
// лимитированная очередь
limitedQueueStatus queueStatus = iota
// безлимитная очередь
unlimitedQueueStatus
)
// лимитированная очередь, в ней будут храниться клиенты к почтовым сервисам
type LimitedQueue struct {
*Queue
// статус, говорящий заблокирована очередь или нет
status queueStatus
// максимальное количество элементов, которое было в очереди
maxLen int
}
// создает новую лимитированную очередь
func NewLimitQueue() *LimitedQueue {
return &LimitedQueue{
Queue: NewQueue(),
status: unlimitedQueueStatus,
}
}
// сигнализирует, что очередь имеет лимит
func (l *LimitedQueue) HasLimit() bool {
l.mutex.Lock()
hasLimit := l.status == limitedQueueStatus
l.mutex.Unlock()
return hasLimit
}
// устанавливает лимит очереди
func (l *LimitedQueue) HasLimitOn() {
if l.MaxLen() > 0 && !l.HasLimit() {
l.setStatus(limitedQueueStatus)
}
}
// снимает лимит очереди
func (l *LimitedQueue) HasLimitOff() {
l.setStatus(unlimitedQueueStatus)
}
// устанавливает статус очереди
func (l *LimitedQueue) setStatus(status queueStatus) {
l.mutex.Lock()
l.status = status
l.mutex.Unlock()
}
// максимальная длина очереди до того момента, как был установлен лимит
func (l *LimitedQueue) MaxLen() int {
l.mutex.Lock()
maxLen := l.maxLen
l.mutex.Unlock()
return maxLen
}
// увеличивает максимальную длину очереди
func (l *LimitedQueue) AddMaxLen() {
l.mutex.Lock()
l.maxLen++
l.mutex.Unlock()
}