%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/waritko/go/src/github.com/odeke-em/semalim/
Upload File :
Create Path :
Current File : //home/waritko/go/src/github.com/odeke-em/semalim/semalim.go

// Copyright 2015 Emmanuel Odeke. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package semalim

type ackType struct{}

var sentinel = ackType{}

type Job interface {
	Id() interface{}
	Do() (interface{}, error)
}

type Result interface {
	Err() error
	Id() interface{}
	Value() interface{}
}

type resultSt struct {
	err   error
	id    interface{}
	value interface{}
}

func (rs resultSt) Err() error         { return rs.err }
func (rs resultSt) Id() interface{}    { return rs.id }
func (rs resultSt) Value() interface{} { return rs.value }

func Run(jobs chan Job, workerCount uint64) chan Result {
	results := make(chan Result)

	doneChan := make(chan ackType)
	slots := make(chan ackType, workerCount)

	slotWait := func() { <-slots }
	slotReady := func() { slots <- sentinel }
	jobDone := func() { doneChan <- sentinel }

	if workerCount < 1 {
		workerCount = 8 // TODO: Define a proper default
	}

	// Make free room for the workerCount
	for i := uint64(0); i < workerCount; i++ {
		slotReady()
	}

	doneCounterChan := make(chan ackType)
	go func() {
		defer close(doneCounterChan)
		for job := range jobs {
			if job != nil {
				doneCounterChan <- sentinel

				go func(j Job) {
					slotWait()

					result, err := j.Do()
					results <- resultSt{id: j.Id(), err: err, value: result}

					slotReady()
					jobDone()
				}(job)
			}
		}
	}()

	go func() {
		defer close(results)
		doneCount := uint64(0)
		for _ = range doneCounterChan {
			doneCount += 1
		}

		// Then finally wait until:
		for i := uint64(0); i < doneCount; i++ {
			<-doneChan
		}
	}()

	return results
}

Zerion Mini Shell 1.0