forked from fsamin/go-wsqueue
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstack.go
132 lines (109 loc) · 2.12 KB
/
stack.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
package wsqueue
import (
"fmt"
"sync"
"time"
)
//Stack is a thread-safe "First In First Out" stack
type Stack struct {
top *stackItem
count int
mutex *sync.Mutex
max int
}
type stackItem struct {
data interface{}
next *stackItem
}
//NewStack intialize a brand new Stack
func NewStack() *Stack {
s := &Stack{}
s.mutex = &sync.Mutex{}
return s
}
//Open the connection to the storage driver
func (s *Stack) Open(o *Options) {
if o != nil {
m := o.Storage
i, b := m["capacity"].(int)
if !b {
Logfunc("Error with stack capacity option : %s", i)
return
}
s.max = i
}
}
// Get peeks at the n-th item in the stack. Unlike other operations, this one costs O(n).
func (s *Stack) Get(index int) (interface{}, error) {
if index < 0 || index >= s.count {
return nil, fmt.Errorf("Requested index %d outside stack, length %d", index, s.count)
}
s.mutex.Lock()
defer s.mutex.Unlock()
n := s.top
for i := 1; i < s.count-index; i++ {
n = n.next
}
return n.data, nil
}
// Dump prints of the stack.
func (s *Stack) Dump() {
n := s.top
fmt.Print("[ ")
for i := 0; i < s.count; i++ {
fmt.Printf("%+v ", n.data)
n = n.next
}
fmt.Print("]")
}
//Len returns current length of the stack
func (s *Stack) Len() int {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.count
}
//Push add an item a the top of the stack
func (s *Stack) Push(item interface{}) {
if s.max > 0 {
f := NewFibonacci()
for s.Len() >= s.max {
Warnfunc("Stack overflow. Waiting...")
f.WaitForIt(time.Second)
}
}
n := &stackItem{data: item}
s.mutex.Lock()
defer s.mutex.Unlock()
if s.top == nil {
s.top = n
} else {
n.next = s.top
s.top = n
}
s.count++
}
//Pop returns and removes the botteom of the stack
func (s *Stack) Pop() interface{} {
s.mutex.Lock()
defer s.mutex.Unlock()
var n *stackItem
if s.top != nil {
n = s.top
s.top = n.next
s.count--
}
if n == nil {
return nil
}
return n.data
}
//Peek returns but doesn't remove the top of the stack
func (s *Stack) Peek() interface{} {
s.mutex.Lock()
defer s.mutex.Unlock()
n := s.top
if n == nil || n.data == nil {
return nil
}
return n.data
}