// Creates a new actor

func NewActor(setActorOptionFuncs ...SetActorOptionFunc) *Actor {

actor := &Actor{buffer: runtime.NumCPU(), quit: make(chan struct{}), wg: &sync.WaitGroup{}}

for _, setOptionFunc := range setActorOptionFuncs {

setOptionFunc(actor)

}

actor.queue = make(chan request, actor.buffer)

actor.wg.Add(1)

go actor.schedule()

return actor

}

// The long live go routine to run.

func (actor *Actor) schedule() {

loop:

for {

select {

case request := <-actor.queue:

request.promise.res, request.promise.err = request.work()

close(request.promise.done)

case <-actor.quit:

break loop

}

}

actor.wg.Done()

}

// Do a work.

func (actor *Actor) Do(workFunc WorkFunc) *Promise {

methodRequest := request{work: workFunc, promise: &Promise{

done: make(chan struct{}),

}}

actor.queue <- methodRequest

return methodRequest.promise

}

// Close actor

func (actor *Actor) Close() {

close(actor.quit)

actor.wg.Wait()

}