func (b *Block) process() Interrupt {
	b.Monitor <- MonitorMessage{
		BI_KERNEL,
		nil,
	}
	if b.state.Processed == true {
		return nil
	}
	if b.sourceType != NONE && b.routing.Source == nil {
		select {
		case f := <-b.routing.InterruptChan:
			return f
		}
	}
	var store sync.Locker
	var ok bool
	if store, ok = b.routing.Source.(sync.Locker); ok {
		store.Lock()
	}
	interrupt := b.kernel(b.state.inputValues,
		b.state.outputValues,
		b.state.internalValues,
		b.routing.Source,
		b.routing.InterruptChan)
	if store != nil {
		store.Unlock()
	}
	if interrupt != nil {
		return interrupt
	}
	b.state.Processed = true
	return nil
}
run kernel on inputs, produce outputs
package core
import (
	"errors"
	"sync"
	"time"
)
func NewBlock(s Spec) *Block {
	var in []Input
	var out []Output
	for _, v := range s.Inputs {
		in = append(in, Input{
			Name:  v.Name,
			Type:  v.Type,
			Value: nil,
			C:     make(chan Message, 1),
		})
	}
	for _, v := range s.Outputs {
		out = append(out, Output{
			Name:        v.Name,
			Type:        v.Type,
			Connections: make(map[Connection]struct{}),
		})
	}
	return &Block{
		state: BlockState{
			make(MessageMap),
			make(MessageMap),
			make(MessageMap),
			make(Manifest),
			false,
		},
		routing: BlockRouting{
			Inputs:        in,
			Outputs:       out,
			InterruptChan: make(chan Interrupt),
		},
		kernel:     s.Kernel,
		sourceType: s.Source,
		Monitor:    make(chan MonitorMessage, 1),
		lastCrank:  time.Now(),
		done:       make(chan struct{}),
	}
}
func (b *Block) Serve() {
	defer func() {
		b.done <- struct{}{}
	}()
	for {
		var interrupt Interrupt
		b.routing.RLock()
		for {
			interrupt = b.receive()
			if interrupt != nil {
				break
			}
			interrupt = b.process()
			if interrupt != nil {
				break
			}
			interrupt = b.broadcast()
			if interrupt != nil {
				break
			}
			b.crank()
		}
		b.routing.RUnlock()
		b.routing.Lock()
		if ok := interrupt(); !ok {
			b.routing.Unlock()
			return
		}
		b.routing.Unlock()
	}
}
func (b *Block) exportInput(id RouteIndex) (*Input, error) {
	if int(id) >= len(b.routing.Inputs) || int(id) < 0 {
		return nil, errors.New("index out of range")
	}
	if b.routing.Inputs[id].Value == nil {
		return &b.routing.Inputs[id], nil
	}
	return &Input{
		Value: &InputValue{
			Data: Copy((*b.routing.Inputs[id].Value).Data),
		},
		C:    b.routing.Inputs[id].C,
		Name: b.routing.Inputs[id].Name,
	}, nil
}
func (b *Block) GetInput(id RouteIndex) (Input, error) {
	b.routing.RLock()
	r, err := b.exportInput(id)
	if err != nil {
		b.routing.RUnlock()
		return Input{}, err
	}
	b.routing.RUnlock()
	return *r, err
}
func (b *Block) GetInputs() []Input {
	b.routing.RLock()
	re := make([]Input, len(b.routing.Inputs), len(b.routing.Inputs))
	for i, _ := range b.routing.Inputs {
		r, _ := b.exportInput(RouteIndex(i))
		re[i] = *r
	}
	b.routing.RUnlock()
	return re
}
func (b *Block) SetInput(id RouteIndex, v *InputValue) error {
	returnVal := make(chan error, 1)
	b.routing.InterruptChan <- func() bool {
		if int(id) < 0 || int(id) >= len(b.routing.Inputs) {
			returnVal <- errors.New("input out of range")
			return true
		}
		if _, ok := b.state.inputValues[id]; ok {
			delete(b.state.inputValues, id)
		}
		b.routing.Inputs[id].Value = v
		returnVal <- nil
		return true
	}
	return <-returnVal
}
func (b *Block) GetOutputs() []Output {
	b.routing.RLock()
	m := make([]Output, len(b.routing.Outputs), len(b.routing.Outputs))
	for id, out := range b.routing.Outputs {
		m[id] = Output{
			Name:        out.Name,
			Type:        out.Type,
			Connections: make(map[Connection]struct{}),
		}
		for k, _ := range out.Connections {
			m[id].Connections[k] = struct{}{}
		}
	}
	b.routing.RUnlock()
	return m
}
func (b *Block) GetSource() Source {
	b.routing.RLock()
	v := b.routing.Source
	b.routing.RUnlock()
	return v
}
func (b *Block) SetSource(s Source) error {
	returnVal := make(chan error, 1)
	b.routing.InterruptChan <- func() bool {
		if s != nil && s.GetType() != b.sourceType {
			returnVal <- errors.New("invalid source type for this block")
			return true
		}
		b.routing.Source = s
		returnVal <- nil
		return true
	}
	return <-returnVal
}
func (b *Block) Connect(id RouteIndex, c Connection) error {
	returnVal := make(chan error, 1)
	b.routing.InterruptChan <- func() bool {
		if int(id) < 0 || int(id) >= len(b.routing.Outputs) {
			returnVal <- errors.New("output out of range")
			return true
		}
		if _, ok := b.routing.Outputs[id].Connections[c]; ok {
			returnVal <- errors.New("this connection already exists on this output")
			return true
		}
		b.routing.Outputs[id].Connections[c] = struct{}{}
		returnVal <- nil
		return true
	}
	return <-returnVal
}
func (b *Block) Disconnect(id RouteIndex, c Connection) error {
	returnVal := make(chan error, 1)
	b.routing.InterruptChan <- func() bool {
		if int(id) < 0 || int(id) >= len(b.routing.Outputs) {
			returnVal <- errors.New("output out of range")
			return true
		}
		if _, ok := b.routing.Outputs[id].Connections[c]; !ok {
			returnVal <- errors.New("connection does not exist")
			return true
		}
		delete(b.routing.Outputs[id].Connections, c)
		returnVal <- nil
		return true
	}
	return <-returnVal
}
func (b *Block) Reset() {
	b.crank()
	for k, _ := range b.state.internalValues {
		delete(b.state.internalValues, k)
	}
	for _, input := range b.routing.Inputs {
		select {
		case <-input.C:
		default:
		}
	}
	return
}
func (b *Block) Stop() {
	b.routing.InterruptChan <- func() bool {
		return false
	}
	<-b.done
	return
}
func (b *Block) receive() Interrupt {
	for id, input := range b.routing.Inputs {
		b.Monitor <- MonitorMessage{
			BI_INPUT,
			id,
		}
		if _, ok := b.state.inputValues[RouteIndex(id)]; ok {
			continue
		}
		if input.Value != nil {
			b.state.inputValues[RouteIndex(id)] = Copy(input.Value.Data)
			continue
		}
		select {
		case m := <-input.C:
			b.state.inputValues[RouteIndex(id)] = m
		case f := <-b.routing.InterruptChan:
			return f
		}
	}
	return nil
}