Add API Framework Revel Source Files
[iec.git] / src / foundation / api / revel / utils / simplestack.go
diff --git a/src/foundation/api/revel/utils/simplestack.go b/src/foundation/api/revel/utils/simplestack.go
new file mode 100644 (file)
index 0000000..bb22430
--- /dev/null
@@ -0,0 +1,103 @@
+package utils
+
+import (
+       "fmt"
+       "sync"
+)
+
+type (
+       SimpleLockStack struct {
+               Current  *SimpleLockStackElement
+               Creator  func() interface{}
+               len      int
+               capacity int
+               active   int
+               maxsize  int
+               lock     sync.Mutex
+       }
+       SimpleLockStackElement struct {
+               Value    interface{}
+               Previous *SimpleLockStackElement
+               Next     *SimpleLockStackElement
+       }
+       ObjectDestroy interface {
+               Destroy()
+       }
+)
+
+func NewStackLock(startsize, maxsize int, creator func() interface{}) *SimpleLockStack {
+       ss := &SimpleLockStack{lock: sync.Mutex{}, Current: &SimpleLockStackElement{Value: creator()}, Creator: creator, maxsize: maxsize}
+       if startsize > 0 {
+               elements := make([]SimpleLockStackElement, startsize-1)
+               current := ss.Current
+               for i := range elements {
+                       e := elements[i]
+                       if creator != nil {
+                               e.Value = creator()
+                       }
+                       current.Next = &e
+                       e.Previous = current
+                       current = &e
+               }
+               ss.capacity, ss.len, ss.active = startsize, startsize, 0
+
+               ss.Current = current
+       }
+       return ss
+}
+func (s *SimpleLockStack) Pop() (value interface{}) {
+       s.lock.Lock()
+       defer s.lock.Unlock()
+       if s.len == 0 {
+               // Pool is empty, create a new item to return
+               if s.Creator != nil {
+                       value = s.Creator()
+               }
+       } else {
+               value = s.Current.Value
+               s.len--
+               if s.Current.Previous != nil {
+                       s.Current = s.Current.Previous
+               }
+       }
+       // println("Pop ",value, s.len, s.active, s.capacity, s.Current.Next)
+       s.active++
+       return
+}
+func (s *SimpleLockStack) Push(value interface{}) {
+       if d, ok := value.(ObjectDestroy); ok {
+               d.Destroy()
+       }
+       s.lock.Lock()
+       defer s.lock.Unlock()
+       if s.len == 0 {
+               s.Current.Value = value
+       } else if s.len < s.maxsize {
+               if s.Current.Next == nil {
+                       s.Current.Next = &SimpleLockStackElement{Value: value, Previous: s.Current}
+                       s.capacity++
+               } else {
+                       s.Current.Next.Value = value
+               }
+               s.Current = s.Current.Next
+       } else {
+               // If we exceeded the capacity of stack do not store the created object
+               return
+       }
+       s.len++
+       s.active--
+       //println("Push ",value, s.len, s.active, s.capacity)
+       return
+}
+func (s *SimpleLockStack) Len() int {
+       return s.len
+}
+func (s *SimpleLockStack) Capacity() int {
+       return s.capacity
+}
+func (s *SimpleLockStack) Active() int {
+       return s.active
+}
+func (s *SimpleLockStack) String() string {
+       return fmt.Sprintf("SS: Capacity:%d Active:%d Stored:%d", s.capacity, s.active, s.len)
+}