func (tp *DocumentsWriterPerThreadPool) newThreadState() (ts *ThreadState) {
	tp.Lock()
	defer tp.Unlock()
	if len(tp.threadStates) < cap(tp.threadStates) {
		ts = newThreadState(len(tp.threadStates))
		tp.threadStates = append(tp.threadStates, ts)
		tp.lockedList.PushBack(ts.id)
	}
	return
}
/*
Returns a new ThreadState iff any new state is available otherwise
nil.

NOTE: the returned ThreadState is already locked iff non-nil.
package index
import (
	"container/list"
	"fmt"
	"sync"
)
type ThreadState struct {
	id   int  
	dwpt *DocumentsWriterPerThread
	flushPending bool  
	bytesUsed int64
	isActive  bool
}
func newThreadState(id int) *ThreadState {
	return &ThreadState{id: id, isActive: true}
}
func (ts *ThreadState) deactivate() {
	ts.isActive = false
	ts.reset()
}
func (ts *ThreadState) reset() {
	ts.dwpt = nil
	ts.bytesUsed = 0
	ts.flushPending = false
}
type DocumentsWriterPerThreadPool struct {
	sync.Locker
	threadStates  []*ThreadState
	listeners     []*list.List
	freeList      *list.List
	lockedList    *list.List
	hasMoreStates *sync.Cond
}
func NewDocumentsWriterPerThreadPool(maxNumThreadStates int) *DocumentsWriterPerThreadPool {
	assert2(maxNumThreadStates >= 1, fmt.Sprintf("maxNumThreadStates must be >= 1 but was: %v", maxNumThreadStates))
	return &DocumentsWriterPerThreadPool{
		Locker:        &sync.Mutex{},
		threadStates:  make([]*ThreadState, 0, maxNumThreadStates),
		listeners:     make([]*list.List, maxNumThreadStates),
		freeList:      list.New(),
		lockedList:    list.New(),
		hasMoreStates: sync.NewCond(&sync.Mutex{}),
	}
}
func (tp *DocumentsWriterPerThreadPool) numActiveThreadState() int {
	return len(tp.threadStates)
}
func (tp *DocumentsWriterPerThreadPool) reset(threadState *ThreadState, closed bool) *DocumentsWriterPerThread {
	dwpt := threadState.dwpt
	if !closed {
		threadState.reset()
	} else {
		threadState.deactivate()
	}
	return dwpt
}
func (tp *DocumentsWriterPerThreadPool) lockAny() (res *ThreadState) {
	for res == nil {
		if res = tp.findNextAvailableThreadState(); res == nil {
			if res = tp.newThreadState(); res == nil {
				func() {
					tp.hasMoreStates.L.Lock()
					defer tp.hasMoreStates.L.Unlock()
					tp.hasMoreStates.Wait()
				}()
			}
		}
	}
	return
}
func (tp *DocumentsWriterPerThreadPool) lock(id int, wait bool) *ThreadState {
	tp.Lock()
	defer tp.Unlock()
	for e := tp.freeList.Front(); e != nil; e = e.Next() {
		if tid := e.Value.(int); tid == id {
			tp.freeList.Remove(e)
			tp.lockedList.PushBack(id)
			return tp.threadStates[tid]
		}
	}
	if !wait {
		return nil
	}
	waitingList := tp.listeners[id]
	if waitingList == nil {
		waitingList = list.New()
		tp.listeners[id] = waitingList
	}
	ch := make(chan *ThreadState)
	waitingList.PushBack(ch)
	return <-ch  
}
func (tp *DocumentsWriterPerThreadPool) findNextAvailableThreadState() *ThreadState {
	tp.Lock()
	defer tp.Unlock()
	if tp.freeList.Len() > 0 {
		e := tp.freeList.Back()
		id := e.Value.(int)
		tp.freeList.Remove(e)
		if tp.threadStates[id].dwpt == nil {
			for e = tp.freeList.Front(); e != nil; e = e.Next() {
				if id2 := e.Value.(int); tp.threadStates[id2].dwpt != nil {
					tp.freeList.PushFront(id)
					id = id2
					tp.freeList.Remove(e)
					break
				}
			}
		}
		return tp.threadStates[id]
	}
	return nil
}