upload nodeb rnib reader version 1.0.5
[ric-plt/nodeb-rnib.git] / common / rNibPool.go
diff --git a/common/rNibPool.go b/common/rNibPool.go
new file mode 100644 (file)
index 0000000..2d90704
--- /dev/null
@@ -0,0 +1,83 @@
+package common
+
+import (
+       "sync/atomic"
+)
+
+type Pool struct {
+       New     func() interface{}
+       Destroy func(interface{})
+       pool    chan interface{}
+       created int32 //Number of objects created
+}
+
+/*
+NewPool creates thread safe Pool object and returns a pointer to it.
+poolSize int - sets the capacity of the pool
+newObj func - specifies a function to generate a value (pool element)
+destroyObj func - specifies a function to destroy a value (pool element)
+*/
+func NewPool(poolSize int, newObj func() interface{}, destroyObj func(interface{})) *Pool{
+       return &Pool{
+               New:     newObj,
+               Destroy: destroyObj,
+               pool:    make(chan interface{}, poolSize),
+       }
+}
+
+/*
+Retrieve an object from the pool.
+If the pool is empty and the number of used object is less than capacity, a new object is created by calling New.
+Otherwise, the method blocks until an object is returned to the pool.
+*/
+func (p *Pool) Get() interface{} {
+       select {
+       case obj := <-p.pool:
+               return obj
+       default:
+               if atomic.AddInt32(&p.created, 1) <= int32(cap(p.pool)) && p.New != nil {
+                       p.pool <- p.New()
+               }
+       }
+       return <-p.pool //block waiting
+}
+
+/*
+Return an object to the pool.
+If capacity is exceeded the object is discarded after calling Destroy on it if Destroy is not nil.
+*/
+func (p *Pool) Put(obj interface{}) {
+       if obj != nil {
+               select {
+               case p.pool <- obj:
+               default:
+                       if p.Destroy != nil {
+                               p.Destroy(obj)
+                       }
+               }
+       }
+}
+
+/*
+ Closes the pool and if Destroy is not nil, call Destroy on each object in the pool
+ The pool must not be used once this method is called.
+*/
+func (p *Pool) Close() {
+       close(p.pool)
+       available := len(p.pool)
+       if p.Destroy != nil {
+               for obj := range p.pool {
+                       p.Destroy(obj)
+
+               }
+       }
+       atomic.AddInt32(&p.created, -int32(available))
+}
+/*
+Return statistics.
+available - the number of available instances
+created - the number of created instances
+*/
+func (p *Pool) Stats() (available int, created int) {
+       return len(p.pool), int(p.created)
+}