func (q *Queue) Len() int64 {
	q.lock.Lock()
	defer q.lock.Unlock()
	return int64(len(q.items))
}
Len returns the number of items in this queue.
package queue
import (
	"runtime"
	"sync"
	"sync/atomic"
)
type waiters []*sema
func (w *waiters) get() *sema {
	if len(*w) == 0 {
		return nil
	}
	sema := (*w)[0]
	copy((*w)[0:], (*w)[1:])
	(*w)[len(*w)-1] = nil  
	*w = (*w)[:len(*w)-1]
	return sema
}
func (w *waiters) put(sema *sema) {
	*w = append(*w, sema)
}
type items []interface{}
func (items *items) get(number int64) []interface{} {
	returnItems := make([]interface{}, 0, number)
	index := int64(0)
	for i := int64(0); i < number; i++ {
		if i >= int64(len(*items)) {
			break
		}
		returnItems = append(returnItems, (*items)[i])
		(*items)[i] = nil
		index++
	}
	*items = (*items)[index:]
	return returnItems
}
func (items *items) getUntil(checker func(item interface{}) bool) []interface{} {
	length := len(*items)
	if len(*items) == 0 {
		return []interface{}{}
	}
	returnItems := make([]interface{}, 0, length)
	index := 0
	for i, item := range *items {
		if !checker(item) {
			break
		}
		returnItems = append(returnItems, item)
		index = i
	}
	*items = (*items)[index:]
	return returnItems
}
type sema struct {
	wg       *sync.WaitGroup
	response *sync.WaitGroup
}
func newSema() *sema {
	return &sema{
		wg:       &sync.WaitGroup{},
		response: &sync.WaitGroup{},
	}
}
type Queue struct {
	waiters  waiters
	items    items
	lock     sync.Mutex
	disposed bool
}
func (q *Queue) Put(items ...interface{}) error {
	if len(items) == 0 {
		return nil
	}
	q.lock.Lock()
	if q.disposed {
		q.lock.Unlock()
		return disposedError
	}
	q.items = append(q.items, items...)
	for {
		sema := q.waiters.get()
		if sema == nil {
			break
		}
		sema.response.Add(1)
		sema.wg.Done()
		sema.response.Wait()
		if len(q.items) == 0 {
			break
		}
	}
	q.lock.Unlock()
	return nil
}
func (q *Queue) Get(number int64) ([]interface{}, error) {
	if number < 1 {
		return []interface{}{}, nil
	}
	q.lock.Lock()
	if q.disposed {
		q.lock.Unlock()
		return nil, disposedError
	}
	var items []interface{}
	if len(q.items) == 0 {
		sema := newSema()
		q.waiters.put(sema)
		sema.wg.Add(1)
		q.lock.Unlock()
		sema.wg.Wait()
		if q.disposed {
			return nil, disposedError
		}
		items = q.items.get(number)
		sema.response.Done()
		return items, nil
	}
	items = q.items.get(number)
	q.lock.Unlock()
	return items, nil
}
func (q *Queue) TakeUntil(checker func(item interface{}) bool) ([]interface{}, error) {
	if checker == nil {
		return nil, nil
	}
	q.lock.Lock()
	if q.disposed {
		q.lock.Unlock()
		return nil, disposedError
	}
	result := q.items.getUntil(checker)
	q.lock.Unlock()
	return result, nil
}
func (q *Queue) Empty() bool {
	q.lock.Lock()
	defer q.lock.Unlock()
	return len(q.items) == 0
}