Add API Framework Revel Source Files
[iec.git] / src / foundation / api / revel / utils / simplestack.go
1 package utils
2
3 import (
4         "fmt"
5         "sync"
6 )
7
8 type (
9         SimpleLockStack struct {
10                 Current  *SimpleLockStackElement
11                 Creator  func() interface{}
12                 len      int
13                 capacity int
14                 active   int
15                 maxsize  int
16                 lock     sync.Mutex
17         }
18         SimpleLockStackElement struct {
19                 Value    interface{}
20                 Previous *SimpleLockStackElement
21                 Next     *SimpleLockStackElement
22         }
23         ObjectDestroy interface {
24                 Destroy()
25         }
26 )
27
28 func NewStackLock(startsize, maxsize int, creator func() interface{}) *SimpleLockStack {
29         ss := &SimpleLockStack{lock: sync.Mutex{}, Current: &SimpleLockStackElement{Value: creator()}, Creator: creator, maxsize: maxsize}
30         if startsize > 0 {
31                 elements := make([]SimpleLockStackElement, startsize-1)
32                 current := ss.Current
33                 for i := range elements {
34                         e := elements[i]
35                         if creator != nil {
36                                 e.Value = creator()
37                         }
38                         current.Next = &e
39                         e.Previous = current
40                         current = &e
41                 }
42                 ss.capacity, ss.len, ss.active = startsize, startsize, 0
43
44                 ss.Current = current
45         }
46         return ss
47 }
48 func (s *SimpleLockStack) Pop() (value interface{}) {
49         s.lock.Lock()
50         defer s.lock.Unlock()
51         if s.len == 0 {
52                 // Pool is empty, create a new item to return
53                 if s.Creator != nil {
54                         value = s.Creator()
55                 }
56         } else {
57                 value = s.Current.Value
58                 s.len--
59                 if s.Current.Previous != nil {
60                         s.Current = s.Current.Previous
61                 }
62         }
63         // println("Pop ",value, s.len, s.active, s.capacity, s.Current.Next)
64         s.active++
65         return
66 }
67 func (s *SimpleLockStack) Push(value interface{}) {
68         if d, ok := value.(ObjectDestroy); ok {
69                 d.Destroy()
70         }
71         s.lock.Lock()
72         defer s.lock.Unlock()
73         if s.len == 0 {
74                 s.Current.Value = value
75         } else if s.len < s.maxsize {
76                 if s.Current.Next == nil {
77                         s.Current.Next = &SimpleLockStackElement{Value: value, Previous: s.Current}
78                         s.capacity++
79                 } else {
80                         s.Current.Next.Value = value
81                 }
82                 s.Current = s.Current.Next
83         } else {
84                 // If we exceeded the capacity of stack do not store the created object
85                 return
86         }
87         s.len++
88         s.active--
89         //println("Push ",value, s.len, s.active, s.capacity)
90         return
91 }
92 func (s *SimpleLockStack) Len() int {
93         return s.len
94 }
95 func (s *SimpleLockStack) Capacity() int {
96         return s.capacity
97 }
98 func (s *SimpleLockStack) Active() int {
99         return s.active
100 }
101 func (s *SimpleLockStack) String() string {
102         return fmt.Sprintf("SS: Capacity:%d Active:%d Stored:%d", s.capacity, s.active, s.len)
103 }