package stackless

import (
	
	
)

// NewFunc returns stackless wrapper for the function f.
//
// Unlike f, the returned stackless wrapper doesn't use stack space
// on the goroutine that calls it.
// The wrapper may save a lot of stack space if the following conditions
// are met:
//
//   - f doesn't contain blocking calls on network, I/O or channels;
//   - f uses a lot of stack space;
//   - the wrapper is called from high number of concurrent goroutines.
//
// The stackless wrapper returns false if the call cannot be processed
// at the moment due to high load.
func ( func( interface{})) func( interface{}) bool {
	if  == nil {
		// developer sanity-check
		panic("BUG: f cannot be nil")
	}

	 := make(chan *funcWork, runtime.GOMAXPROCS(-1)*2048)
	 := func() {
		 := runtime.GOMAXPROCS(-1)
		for  := 0;  < ; ++ {
			go funcWorker(, )
		}
	}
	var  sync.Once

	return func( interface{}) bool {
		.Do()
		 := getFuncWork()
		.ctx = 

		select {
		case  <- :
		default:
			putFuncWork()
			return false
		}
		<-.done
		putFuncWork()
		return true
	}
}

func funcWorker( <-chan *funcWork,  func( interface{})) {
	for  := range  {
		(.ctx)
		.done <- struct{}{}
	}
}

func getFuncWork() *funcWork {
	 := funcWorkPool.Get()
	if  == nil {
		 = &funcWork{
			done: make(chan struct{}, 1),
		}
	}
	return .(*funcWork)
}

func putFuncWork( *funcWork) {
	.ctx = nil
	funcWorkPool.Put()
}

var funcWorkPool sync.Pool

type funcWork struct {
	ctx  interface{}
	done chan struct{}
}