func (cnn *serverConn) handle(chpv reflect.Value, name []byte) { handler := func(ws *websocket.Conn) { // send go func() { for { if v, ok := chpv.Recv(); ok { cnn.codec.Send(ws, v) } else { panic(Closed) } } }() // recieve for { v := reflect.New(chpv.Type().Elem()) cnn.codec.Receive(ws, v.Interface()) chpv.Send(reflect.Indirect(v)) } } encodedName := base64.URLEncoding.EncodeToString(name) if _, ok := cnn.channels[encodedName]; !ok { cnn.channels[encodedName] = true pattern := fmt.Sprintf("/%s", encodedName) cnn.handlers.Handle(pattern, websocket.Handler(handler)) } }
func doChanWrite(valCh, argVal reflect.Value) { chType := valCh.Type().Elem() if argVal.Type().ConvertibleTo(chType) { argVal = argVal.Convert(chType) } for { valCh.Send(argVal) } }
func pMapChanInt(inChan reflect.Value, f interface{}, outChan reflect.Value) { fVal := reflect.ValueOf(f) val, ok := inChan.Recv() for ok { results := fVal.Call([]reflect.Value{val}) outChan.Send(results[0]) val, ok = inChan.Recv() } outChan.Close() }
func sendKeyValues(outChan reflect.Value, key interface{}, valueType reflect.Type, values []interface{}) { sliceElementType := reflect.SliceOf(valueType) sliceLen := len(values) sliceValue := reflect.MakeSlice(sliceElementType, sliceLen, sliceLen) for i, value := range values { sliceValue.Index(i).Set(reflect.ValueOf(value)) } outChan.Send(reflect.ValueOf(KeyValues{key, sliceValue.Interface()})) }
func pMapDrainOutChans(outChans []reflect.Value, resultChan reflect.Value) { numChans := len(outChans) idx := 0 val, ok := outChans[idx].Recv() for ok { resultChan.Send(val) idx++ val, ok = outChans[idx%numChans].Recv() } resultChan.Close() }
func mapWorker(fn reflect.Value, job chan []reflect.Value, res reflect.Value) { for { v, ok := <-job if !ok { break } if len(v) > 0 { r := fn.Call(v) res.Send(r[0]) } } }
// the value over the outChan is always reflect.Value // but the inner values are always actual interface{} object func sendMapOutputs(outChan reflect.Value, values []reflect.Value) { if !outChan.IsValid() { return } if len(values) == 2 { outChan.Send(reflect.ValueOf(KeyValue{values[0].Interface(), values[1].Interface()})) return } if len(values) == 1 { outChan.Send(values[0]) return } }
func (t *Transport) toChan(cid uint64, cval reflect.Value) error { // Type check! woo if cval.Kind() != reflect.Chan { return fmt.Errorf("fatchan: cannot connect a %s - must be a channel", cval.Type()) } if cval.Type().ChanDir()&reflect.SendDir == 0 { return fmt.Errorf("fatchan: cannot connect a %s - recieve-only channel", cval.Type()) } // Register our channel recv := make(chan []byte, 32) reg := ®ister{ cid: cid, data: recv, done: make(done, 1), } t.query <- reg <-reg.done sid, cid := t.sid, reg.cid go func() { // Close the channel when we return defer cval.Close() // TODO(kevlar): Catch close of closed channel? // Unregister the channel when we return defer func() { select { case t.msg <- &unregister{cid: cid}: case <-time.After(10 * time.Millisecond): // TODO(kevlar): Is this prefereable to closing the channel // and catching the panic? I'm not sure. Would it be possible // to use a WaitGroup to know when to close the query channel? } }() etyp := cval.Type().Elem() for data := range recv { t.debug("[%d] new data %q", cid, data) v := reflect.New(etyp).Elem() if err := t.decodeValue(bytes.NewReader(data), v); err != nil { t.err(sid, cid, err) return } t.debug("[%d] sending %#v", cid, v.Interface()) cval.Send(v) } }() return nil }
func sendKeyValuesValues(outChan reflect.Value, key interface{}, leftType reflect.Type, leftValues []interface{}, rightType reflect.Type, rightValues []interface{}) { slice1Len := len(leftValues) slice1Value := reflect.MakeSlice(reflect.SliceOf(leftType), slice1Len, slice1Len) for i, value := range leftValues { slice1Value.Index(i).Set(reflect.ValueOf(value)) } slice2Len := len(rightValues) slice2Value := reflect.MakeSlice(reflect.SliceOf(rightType), slice2Len, slice2Len) for i, value := range rightValues { slice2Value.Index(i).Set(reflect.ValueOf(value)) } outChan.Send(reflect.ValueOf(KeyValuesValues{key, slice1Value.Interface(), slice2Value.Interface()})) }
// the value over the outChan is always reflect.Value // but the inner values are always actual interface{} object func sendValues(outChan reflect.Value, values []reflect.Value) { var infs []interface{} for _, v := range values { infs = append(infs, v.Interface()) } if !outChan.IsValid() { return } if len(infs) > 1 { outChan.Send(reflect.ValueOf(infs)) return } if len(infs) == 1 { outChan.Send(reflect.ValueOf(infs[0])) return } }
func sendKeyValuesValues(outChan reflect.Value, key interface{}, valueType reflect.Type, values1, values2 []interface{}) { sliceType := reflect.SliceOf(valueType) slice1Len := len(values1) slice1Value := reflect.MakeSlice(sliceType, slice1Len, slice1Len) for i, value := range values1 { slice1Value.Index(i).Set(reflect.ValueOf(value)) } slice2Len := len(values2) slice2Value := reflect.MakeSlice(sliceType, slice2Len, slice2Len) for i, value := range values2 { slice2Value.Index(i).Set(reflect.ValueOf(value)) } outChan.Send(reflect.ValueOf(KeyValuesValues{key, slice1Value.Interface(), slice2Value.Interface()})) }
func (t *Transport) toChan(cval reflect.Value) (uint64, uint64, error) { sid, cid := t.sid, atomic.AddUint64(&t.nextCID, 1) // Type check! woo if cval.Kind() != reflect.Chan { return sid, cid, fmt.Errorf("fatchan: cannot connect a %s - must be a channel", cval.Type()) } if cval.Type().ChanDir()&reflect.SendDir == 0 { return sid, cid, fmt.Errorf("fatchan: cannot connect a %s - recieve-only channel", cval.Type()) } // Register our data recv := make(chan []byte, 32) t.reg <- register{cid, recv} // Peruse the element type etyp := cval.Type().Elem() go func() { defer cval.Close() defer func() { t.unreg <- unregister{cid} }() for data := range recv { v := reflect.New(etyp).Elem() if err := t.decodeValue(bytes.NewReader(data), v); err != nil { t.err(t.sid, cid, err) return } cval.Send(v) } }() return sid, cid, nil }
func send(outChan reflect.Value, values ...interface{}) { outChan.Send(reflect.ValueOf(values)) }
// run runs the network and waits for all processes to finish. func (n *Graph) run() { // Add processes to the waitgroup before starting them nump := len(n.procs) n.waitGrp.Add(nump) for _, v := range n.procs { // Check if it is a net or proc r := reflect.ValueOf(v).Elem() if r.FieldByName("Graph").IsValid() { RunNet(v) } else { RunProc(v) } } n.isRunning = true // Send initial IPs for _, ip := range n.iips { // Get the reciever port var rport reflect.Value found := false // Try to find it among network inports for _, inPort := range n.inPorts { if inPort.proc == ip.proc && inPort.port == ip.port { rport = inPort.channel found = true break } } if !found { // Try to find among connections for _, conn := range n.connections { if conn.tgt.Proc == ip.proc && conn.tgt.Port == ip.port { rport = conn.channel found = true break } } } if !found { // Try to find a proc and attach a new channel to it for procName, proc := range n.procs { if procName == ip.proc { // Check if receiver is a net rv := reflect.ValueOf(proc).Elem() var rnet reflect.Value if rv.Type().Name() == "Graph" { rnet = rv } else { rnet = rv.FieldByName("Graph") } if rnet.IsValid() { if pm, isPm := rnet.Addr().Interface().(portMapper); isPm { rport = pm.getInPort(ip.port) } } else { // Receiver is a proc rport = rv.FieldByName(ip.port) } // Validate receiver port rtport := rport.Type() if rtport.Kind() != reflect.Chan || rtport.ChanDir()&reflect.RecvDir == 0 { panic(ip.proc + "." + ip.port + " is not a valid input channel") } var channel reflect.Value // Make a channel of an appropriate type chanType := reflect.ChanOf(reflect.BothDir, rtport.Elem()) channel = reflect.MakeChan(chanType, DefaultBufferSize) // Set the channel if rport.CanSet() { rport.Set(channel) } else { panic(ip.proc + "." + ip.port + " is not settable") } // Use the new channel to send the IIP rport = channel found = true break } } } if found { // Send data to the port rport.Send(reflect.ValueOf(ip.data)) } else { panic("IIP target not found: " + ip.proc + "." + ip.port) } } // Let the outside world know that the network is ready close(n.ready) // Wait for all processes to terminate n.waitGrp.Wait() n.isRunning = false // Check if there is a parent net if n.Net != nil { // Notify parent of finish n.Net.waitGrp.Done() } }
func (f decFnInfo) kSlice(rv reflect.Value) { // A slice can be set from a map or array in stream. // This way, the order can be kept (as order is lost with map). ti := f.ti d := f.d if f.dd.IsContainerType(valueTypeBytes) || f.dd.IsContainerType(valueTypeString) { if ti.rtid == uint8SliceTypId || ti.rt.Elem().Kind() == reflect.Uint8 { if f.seq == seqTypeChan { bs2 := f.dd.DecodeBytes(nil, false, true) ch := rv.Interface().(chan<- byte) for _, b := range bs2 { ch <- b } } else { rvbs := rv.Bytes() bs2 := f.dd.DecodeBytes(rvbs, false, false) if rvbs == nil && bs2 != nil || rvbs != nil && bs2 == nil || len(bs2) != len(rvbs) { if rv.CanSet() { rv.SetBytes(bs2) } else { copy(rvbs, bs2) } } } return } } // array := f.seq == seqTypeChan slh, containerLenS := d.decSliceHelperStart() // an array can never return a nil slice. so no need to check f.array here. if rv.IsNil() { // either chan or slice if f.seq == seqTypeSlice { if containerLenS <= 0 { rv.Set(reflect.MakeSlice(ti.rt, 0, 0)) } else { rv.Set(reflect.MakeSlice(ti.rt, containerLenS, containerLenS)) } } else if f.seq == seqTypeChan { if containerLenS <= 0 { rv.Set(reflect.MakeChan(ti.rt, 0)) } else { rv.Set(reflect.MakeChan(ti.rt, containerLenS)) } } } rvlen := rv.Len() if containerLenS == 0 { if f.seq == seqTypeSlice && rvlen != 0 { rv.SetLen(0) } // slh.End() // f.dd.ReadArrayEnd() return } rtelem0 := ti.rt.Elem() rtelem := rtelem0 for rtelem.Kind() == reflect.Ptr { rtelem = rtelem.Elem() } fn := d.getDecFn(rtelem, true, true) rv0 := rv rvChanged := false rvcap := rv.Cap() // for j := 0; j < containerLenS; j++ { hasLen := containerLenS >= 0 if hasLen { if f.seq == seqTypeChan { // handle chan specially: for j := 0; j < containerLenS; j++ { rv0 := reflect.New(rtelem0).Elem() d.decodeValue(rv0, fn) rv.Send(rv0) } } else { numToRead := containerLenS if containerLenS > rvcap { if f.seq == seqTypeArray { d.arrayCannotExpand(rv.Len(), containerLenS) numToRead = rvlen } else { rv = reflect.MakeSlice(ti.rt, containerLenS, containerLenS) if rvlen > 0 && !isMutableKind(ti.rt.Kind()) { rv1 := rv0 rv1.SetLen(rvcap) reflect.Copy(rv, rv1) } rvChanged = true rvlen = containerLenS } } else if containerLenS != rvlen { rv.SetLen(containerLenS) rvlen = containerLenS } j := 0 for ; j < numToRead; j++ { d.decodeValue(rv.Index(j), fn) } if f.seq == seqTypeArray { for ; j < containerLenS; j++ { d.swallow() } } } } else { for j := 0; !f.dd.CheckBreak(); j++ { var decodeIntoBlank bool // if indefinite, etc, then expand the slice if necessary if j >= rvlen { if f.seq == seqTypeArray { d.arrayCannotExpand(rvlen, j+1) decodeIntoBlank = true } else if f.seq == seqTypeSlice { rv = reflect.Append(rv, reflect.Zero(rtelem0)) rvlen++ rvChanged = true } } if j > 0 { slh.Sep(j) } if f.seq == seqTypeChan { rv0 := reflect.New(rtelem0).Elem() d.decodeValue(rv0, fn) rv.Send(rv0) } else if decodeIntoBlank { d.swallow() } else { d.decodeValue(rv.Index(j), fn) } } slh.End() } if rvChanged { rv0.Set(rv) } }
func (f *decFnInfo) kSlice(rv reflect.Value) { // A slice can be set from a map or array in stream. // This way, the order can be kept (as order is lost with map). ti := f.ti d := f.d dd := d.d rtelem0 := ti.rt.Elem() if dd.IsContainerType(valueTypeBytes) || dd.IsContainerType(valueTypeString) { if ti.rtid == uint8SliceTypId || rtelem0.Kind() == reflect.Uint8 { if f.seq == seqTypeChan { bs2 := dd.DecodeBytes(nil, false, true) ch := rv.Interface().(chan<- byte) for _, b := range bs2 { ch <- b } } else { rvbs := rv.Bytes() bs2 := dd.DecodeBytes(rvbs, false, false) if rvbs == nil && bs2 != nil || rvbs != nil && bs2 == nil || len(bs2) != len(rvbs) { if rv.CanSet() { rv.SetBytes(bs2) } else { copy(rvbs, bs2) } } } return } } // array := f.seq == seqTypeChan slh, containerLenS := d.decSliceHelperStart() var rvlen, numToRead int var truncated bool // says that the len of the sequence is not same as the expected number of elements. numToRead = containerLenS // if truncated, reset numToRead // an array can never return a nil slice. so no need to check f.array here. if rv.IsNil() { // either chan or slice if rvlen, truncated = decInferLen(containerLenS, f.d.h.MaxInitLen, int(rtelem0.Size())); truncated { numToRead = rvlen } if f.seq == seqTypeSlice { rv.Set(reflect.MakeSlice(ti.rt, rvlen, rvlen)) } else if f.seq == seqTypeChan { rv.Set(reflect.MakeChan(ti.rt, rvlen)) } } else { rvlen = rv.Len() } if containerLenS == 0 { if f.seq == seqTypeSlice && rvlen != 0 { rv.SetLen(0) } // dd.ReadEnd() return } rtelem := rtelem0 for rtelem.Kind() == reflect.Ptr { rtelem = rtelem.Elem() } fn := d.getDecFn(rtelem, true, true) var rv0, rv9 reflect.Value rv0 = rv rvChanged := false rvcap := rv.Cap() // for j := 0; j < containerLenS; j++ { if containerLenS >= 0 { // hasLen if f.seq == seqTypeChan { // handle chan specially: for j := 0; j < containerLenS; j++ { rv9 = reflect.New(rtelem0).Elem() d.decodeValue(rv9, fn) rv.Send(rv9) } } else { // slice or array if containerLenS > rvcap { if f.seq == seqTypeArray { d.arrayCannotExpand(rvlen, containerLenS) } else { oldRvlenGtZero := rvlen > 0 rvlen, truncated = decInferLen(containerLenS, f.d.h.MaxInitLen, int(rtelem0.Size())) rv = reflect.MakeSlice(ti.rt, rvlen, rvlen) if oldRvlenGtZero && !isImmutableKind(rtelem0.Kind()) { reflect.Copy(rv, rv0) // only copy up to length NOT cap i.e. rv0.Slice(0, rvcap) } rvChanged = true } numToRead = rvlen } else if containerLenS != rvlen { if f.seq == seqTypeSlice { rv.SetLen(containerLenS) rvlen = containerLenS } } j := 0 // we read up to the numToRead for ; j < numToRead; j++ { d.decodeValue(rv.Index(j), fn) } // if slice, expand and read up to containerLenS (or EOF) iff truncated // if array, swallow all the rest. if f.seq == seqTypeArray { for ; j < containerLenS; j++ { d.swallow() } } else if truncated { // slice was truncated, as chan NOT in this block for ; j < containerLenS; j++ { rv = expandSliceValue(rv, 1) rv9 = rv.Index(j) if resetSliceElemToZeroValue { rv9.Set(reflect.Zero(rtelem0)) } d.decodeValue(rv9, fn) } } } } else { for j := 0; !dd.CheckBreak(); j++ { var decodeIntoBlank bool // if indefinite, etc, then expand the slice if necessary if j >= rvlen { if f.seq == seqTypeArray { d.arrayCannotExpand(rvlen, j+1) decodeIntoBlank = true } else if f.seq == seqTypeSlice { // rv = reflect.Append(rv, reflect.Zero(rtelem0)) // uses append logic, plus varargs rv = expandSliceValue(rv, 1) rv9 = rv.Index(j) // rv.Index(rv.Len() - 1).Set(reflect.Zero(rtelem0)) if resetSliceElemToZeroValue { rv9.Set(reflect.Zero(rtelem0)) } rvlen++ rvChanged = true } } else if f.seq != seqTypeChan { // slice or array rv9 = rv.Index(j) } if f.seq == seqTypeChan { rv9 = reflect.New(rtelem0).Elem() d.decodeValue(rv9, fn) rv.Send(rv9) } else if decodeIntoBlank { d.swallow() } else { // seqTypeSlice d.decodeValue(rv9, fn) } } slh.End() } if rvChanged { rv0.Set(rv) } }
func sendKeyValueValue(outChan reflect.Value, key, a, b interface{}) { outChan.Send(reflect.ValueOf(KeyValueValue{key, a, b})) }