func (mb *MB) Close() (err error) {
	mb.cond.L.Lock()
	if mb.closed {
		mb.cond.L.Unlock()
		return ErrClosed
	}
	mb.closed = true
	mb.unlockAdd()
	mb.cond.L.Unlock()
	mb.cond.Broadcast()
	return
}
Close closes the queue
All added messages will be available for Wait
When queue paused messages do not be released for Wait (use GetAll for fetching them)
package mb
import (
	"errors"
	"sync"
)
var ErrClosed = errors.New("mb: MB closed")
var ErrTooManyMessages = errors.New("mb: too many messages")
var ErrOverflowed = errors.New("mb: overflowed")
func New(size int) *MB {
	return &MB{
		cond: sync.NewCond(&sync.Mutex{}),
		size: size,
		read: make(chan struct{}),
	}
}
type MB struct {
	msgs []interface{}
	cond *sync.Cond
	size int
	wait int
	read chan struct{}
	paused, closed bool
	addCount, getCount         int64
	addMsgsCount, getMsgsCount int64
}
func (mb *MB) Wait() (msgs []interface{}) {
	return mb.WaitMinMax(0, 0)
}
func (mb *MB) WaitMax(max int) (msgs []interface{}) {
	return mb.WaitMinMax(0, max)
}
func (mb *MB) WaitMin(min int) (msgs []interface{}) {
	return mb.WaitMinMax(min, 0)
}
func (mb *MB) WaitMinMax(min, max int) (msgs []interface{}) {
	if min <= 0 {
		min = 1
	}
	mb.cond.L.Lock()
try:
	if len(mb.msgs) < min || mb.paused {
		if mb.closed {
			mb.cond.L.Unlock()
			return
		}
		mb.cond.Wait()
		goto try
	}
	if max > 0 && len(mb.msgs) > max {
		msgs = mb.msgs[:max]
		mb.msgs = mb.msgs[max:]
	} else {
		msgs = mb.msgs
		mb.msgs = make([]interface{}, 0)
	}
	mb.getCount++
	mb.getMsgsCount += int64(len(msgs))
	mb.unlockAdd()
	mb.cond.L.Unlock()
	return
}
func (mb *MB) GetAll() (msgs []interface{}) {
	mb.cond.L.Lock()
	msgs = mb.msgs
	mb.msgs = make([]interface{}, 0)
	mb.getCount++
	mb.getMsgsCount += int64(len(msgs))
	mb.unlockAdd()
	mb.cond.L.Unlock()
	return
}
func (mb *MB) Add(msgs ...interface{}) (err error) {
add:
	mb.cond.L.Lock()
	if mb.closed {
		mb.cond.L.Unlock()
		return ErrClosed
	}
	if mb.size > 0 && len(mb.msgs)+len(msgs) > mb.size {
		if len(msgs) > mb.size {
			mb.cond.L.Unlock()
			return ErrTooManyMessages
		}
		mb.wait++
		mb.cond.L.Unlock()
		<-mb.read
		goto add
	}
	mb.msgs = append(mb.msgs, msgs...)
	mb.addCount++
	mb.addMsgsCount += int64(len(msgs))
	paused := mb.paused
	mb.cond.L.Unlock()
	if !paused {
		mb.cond.Signal()
	}
	return
}
func (mb *MB) TryAdd(msgs ...interface{}) (err error) {
	mb.cond.L.Lock()
	if mb.closed {
		mb.cond.L.Unlock()
		return ErrClosed
	}
	if mb.size > 0 && len(mb.msgs)+len(msgs) > mb.size {
		if len(msgs) > mb.size {
			mb.cond.L.Unlock()
			return ErrTooManyMessages
		}
		mb.cond.L.Unlock()
		return ErrOverflowed
	}
	mb.msgs = append(mb.msgs, msgs...)
	mb.addCount++
	mb.addMsgsCount += int64(len(msgs))
	paused := mb.paused
	mb.cond.L.Unlock()
	if !paused {
		mb.cond.Signal()
	}
	return
}
func (mb *MB) unlockAdd() {
	if mb.wait > 0 {
		for i := 0; i < mb.wait; i++ {
			mb.read <- struct{}{}
		}
		mb.wait = 0
	}
}
func (mb *MB) Pause() {
	mb.cond.L.Lock()
	mb.paused = true
	mb.cond.L.Unlock()
}
func (mb *MB) Resume() {
	mb.cond.L.Lock()
	wasPaused := mb.paused
	mb.paused = false
	mb.cond.L.Unlock()
	if wasPaused {
		mb.cond.Broadcast()
	}
}
func (mb *MB) Len() (l int) {
	mb.cond.L.Lock()
	l = len(mb.msgs)
	mb.cond.L.Unlock()
	return
}
func (mb *MB) Stats() (addCount, addMsgsCount, getCount, getMsgsCount int64) {
	mb.cond.L.Lock()
	addCount, addMsgsCount, getCount, getMsgsCount =
		mb.addCount, mb.addMsgsCount, mb.getCount, mb.getMsgsCount
	mb.cond.L.Unlock()
	return
}