mirror of
https://github.com/golang/go
synced 2024-10-03 04:21:22 -06:00
reflection for channels
R=r DELTA=188 (171 added, 6 deleted, 11 changed) OCL=31352 CL=31361
This commit is contained in:
parent
2ad7958b7e
commit
5ddaf9a098
@ -598,7 +598,7 @@ func TestNilPtrValueSub(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMapAccess(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
m := map[string]int{ "a": 1, "b": 2 };
|
m := map[string]int{ "a": 1, "b": 2 };
|
||||||
mv := NewValue(m).(*MapValue);
|
mv := NewValue(m).(*MapValue);
|
||||||
if n := mv.Len(); n != len(m) {
|
if n := mv.Len(); n != len(m) {
|
||||||
@ -651,3 +651,77 @@ func TestMapAccess(t *testing.T) {
|
|||||||
t.Errorf("newm[\"a\"] = %d after delete", v);
|
t.Errorf("newm[\"a\"] = %d after delete", v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestChan(t *testing.T) {
|
||||||
|
for loop := 0; loop < 2; loop++ {
|
||||||
|
var c chan int;
|
||||||
|
var cv *ChanValue;
|
||||||
|
|
||||||
|
// check both ways to allocate channels
|
||||||
|
switch loop {
|
||||||
|
case 1:
|
||||||
|
c = make(chan int, 1);
|
||||||
|
cv = NewValue(c).(*ChanValue);
|
||||||
|
case 0:
|
||||||
|
cv = MakeChan(Typeof(c).(*ChanType), 1);
|
||||||
|
c = cv.Interface().(chan int);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send
|
||||||
|
cv.Send(NewValue(2));
|
||||||
|
if i := <-c; i != 2 {
|
||||||
|
t.Errorf("reflect Send 2, native recv %d", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recv
|
||||||
|
c <- 3;
|
||||||
|
if i := cv.Recv().(*IntValue).Get(); i != 3 {
|
||||||
|
t.Errorf("native send 3, reflect Recv %d", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryRecv fail
|
||||||
|
val := cv.TryRecv();
|
||||||
|
if val != nil {
|
||||||
|
t.Errorf("TryRecv on empty chan: %s", valueToString(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryRecv success
|
||||||
|
c <- 4;
|
||||||
|
val = cv.TryRecv();
|
||||||
|
if val == nil {
|
||||||
|
t.Errorf("TryRecv on ready chan got nil");
|
||||||
|
} else if i := val.(*IntValue).Get(); i != 4 {
|
||||||
|
t.Errorf("native send 4, TryRecv %d", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrySend fail
|
||||||
|
c <- 100;
|
||||||
|
ok := cv.TrySend(NewValue(5));
|
||||||
|
i := <-c;
|
||||||
|
if ok {
|
||||||
|
t.Errorf("TrySend on full chan succeeded: value %d", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrySend success
|
||||||
|
ok = cv.TrySend(NewValue(6));
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("TrySend on empty chan failed");
|
||||||
|
} else {
|
||||||
|
if i = <-c; i != 6 {
|
||||||
|
t.Errorf("TrySend 6, recv %d", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check creation of unbuffered channel
|
||||||
|
var c chan int;
|
||||||
|
cv := MakeChan(Typeof(c).(*ChanType), 0);
|
||||||
|
c = cv.Interface().(chan int);
|
||||||
|
if cv.TrySend(NewValue(7)) {
|
||||||
|
t.Errorf("TrySend on sync chan succeeded");
|
||||||
|
}
|
||||||
|
if cv.TryRecv() != nil {
|
||||||
|
t.Errorf("TryRecv on sync chan succeeded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -631,26 +631,74 @@ func (v *ChanValue) Get() uintptr {
|
|||||||
return *(*uintptr)(v.addr);
|
return *(*uintptr)(v.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implemented in ../pkg/runtime/reflect.cgo
|
||||||
|
func makechan(typ *runtime.ChanType, size uint32) (ch *byte)
|
||||||
|
func chansend(ch, val *byte, pres *bool)
|
||||||
|
func chanrecv(ch, val *byte, pres *bool)
|
||||||
|
|
||||||
|
// internal send; non-blocking if b != nil
|
||||||
|
func (v *ChanValue) send(x Value, b *bool) {
|
||||||
|
t := v.Type().(*ChanType);
|
||||||
|
if t.Dir() & SendDir == 0{
|
||||||
|
panic("send on recv-only channel");
|
||||||
|
}
|
||||||
|
ch := *(**byte)(v.addr);
|
||||||
|
chansend(ch, (*byte)(x.getAddr()), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal recv; non-blocking if b != nil
|
||||||
|
func (v *ChanValue) recv(b *bool) Value {
|
||||||
|
t := v.Type().(*ChanType);
|
||||||
|
if t.Dir() & RecvDir == 0 {
|
||||||
|
panic("recv on send-only channel");
|
||||||
|
}
|
||||||
|
ch := *(**byte)(v.addr);
|
||||||
|
newval := MakeZero(t.Elem());
|
||||||
|
x := MakeZero(t.Elem());
|
||||||
|
chanrecv(ch, (*byte)(x.getAddr()), b);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
// Send sends x on the channel v.
|
// Send sends x on the channel v.
|
||||||
func (v *ChanValue) Send(x Value) {
|
func (v *ChanValue) Send(x Value) {
|
||||||
panic("unimplemented: channel Send");
|
v.send(x, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recv receives and returns a value from the channel v.
|
// Recv receives and returns a value from the channel v.
|
||||||
func (v *ChanValue) Recv() Value {
|
func (v *ChanValue) Recv() Value {
|
||||||
panic("unimplemented: channel Receive");
|
return v.recv(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrySend attempts to sends x on the channel v but will not block.
|
// TrySend attempts to sends x on the channel v but will not block.
|
||||||
// It returns true if the value was sent, false otherwise.
|
// It returns true if the value was sent, false otherwise.
|
||||||
func (v *ChanValue) TrySend(x Value) bool {
|
func (v *ChanValue) TrySend(x Value) bool {
|
||||||
panic("unimplemented: channel TrySend");
|
var ok bool;
|
||||||
|
v.send(x, &ok);
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryRecv attempts to receive a value from the channel v but will not block.
|
// TryRecv attempts to receive a value from the channel v but will not block.
|
||||||
// It returns the value if one is received, nil otherwise.
|
// It returns the value if one is received, nil otherwise.
|
||||||
func (v *ChanValue) TryRecv() Value {
|
func (v *ChanValue) TryRecv() Value {
|
||||||
panic("unimplemented: channel TryRecv");
|
var ok bool;
|
||||||
|
x := v.recv(&ok);
|
||||||
|
if !ok {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeChan creates a new channel with the specified type and buffer size.
|
||||||
|
func MakeChan(typ *ChanType, buffer int) *ChanValue {
|
||||||
|
if buffer < 0 {
|
||||||
|
panic("MakeChan: negative buffer size");
|
||||||
|
}
|
||||||
|
if typ.Dir() != BothDir {
|
||||||
|
panic("MakeChan: unidirectional channel type");
|
||||||
|
}
|
||||||
|
v := MakeZero(typ).(*ChanValue);
|
||||||
|
*(**byte)(v.addr) = makechan((*runtime.ChanType)(unsafe.Pointer(typ)), uint32(buffer));
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -818,6 +866,7 @@ func (v *MapValue) Keys() []Value {
|
|||||||
return a[0:i];
|
return a[0:i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeMap creates a new map of the specified type.
|
||||||
func MakeMap(typ *MapType) *MapValue {
|
func MakeMap(typ *MapType) *MapValue {
|
||||||
v := MakeZero(typ).(*MapValue);
|
v := MakeZero(typ).(*MapValue);
|
||||||
*(**byte)(v.addr) = makemap((*runtime.MapType)(unsafe.Pointer(typ)));
|
*(**byte)(v.addr) = makemap((*runtime.MapType)(unsafe.Pointer(typ)));
|
||||||
|
@ -15,7 +15,6 @@ enum
|
|||||||
Emax = 0x0800, // error limit before throw
|
Emax = 0x0800, // error limit before throw
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Hchan Hchan;
|
|
||||||
typedef struct Link Link;
|
typedef struct Link Link;
|
||||||
typedef struct WaitQ WaitQ;
|
typedef struct WaitQ WaitQ;
|
||||||
typedef struct SudoG SudoG;
|
typedef struct SudoG SudoG;
|
||||||
@ -88,10 +87,8 @@ static uint32 gcd(uint32, uint32);
|
|||||||
static uint32 fastrand1(void);
|
static uint32 fastrand1(void);
|
||||||
static uint32 fastrand2(void);
|
static uint32 fastrand2(void);
|
||||||
|
|
||||||
// newchan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any);
|
Hchan*
|
||||||
void
|
makechan(uint32 elemsize, uint32 elemalg, uint32 hint)
|
||||||
sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint,
|
|
||||||
Hchan* ret)
|
|
||||||
{
|
{
|
||||||
Hchan *c;
|
Hchan *c;
|
||||||
int32 i;
|
int32 i;
|
||||||
@ -126,9 +123,6 @@ sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint,
|
|||||||
c->dataqsiz = hint;
|
c->dataqsiz = hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = c;
|
|
||||||
FLUSH(&ret);
|
|
||||||
|
|
||||||
if(debug) {
|
if(debug) {
|
||||||
prints("newchan: chan=");
|
prints("newchan: chan=");
|
||||||
sys·printpointer(c);
|
sys·printpointer(c);
|
||||||
@ -140,6 +134,16 @@ sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint,
|
|||||||
sys·printint(c->dataqsiz);
|
sys·printint(c->dataqsiz);
|
||||||
prints("\n");
|
prints("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// newchan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any);
|
||||||
|
void
|
||||||
|
sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint, Hchan *ret)
|
||||||
|
{
|
||||||
|
ret = makechan(elemsize, elemalg, hint);
|
||||||
|
FLUSH(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -162,7 +166,7 @@ incerr(Hchan* c)
|
|||||||
* not complete
|
* not complete
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
sendchan(Hchan *c, byte *ep, bool *pres)
|
chansend(Hchan *c, byte *ep, bool *pres)
|
||||||
{
|
{
|
||||||
SudoG *sg;
|
SudoG *sg;
|
||||||
G* gp;
|
G* gp;
|
||||||
@ -266,7 +270,7 @@ closed:
|
|||||||
unlock(&chanlock);
|
unlock(&chanlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
chanrecv(Hchan* c, byte *ep, bool* pres)
|
chanrecv(Hchan* c, byte *ep, bool* pres)
|
||||||
{
|
{
|
||||||
SudoG *sg;
|
SudoG *sg;
|
||||||
@ -381,7 +385,7 @@ sys·chansend1(Hchan* c, ...)
|
|||||||
|
|
||||||
o = rnd(sizeof(c), c->elemsize);
|
o = rnd(sizeof(c), c->elemsize);
|
||||||
ae = (byte*)&c + o;
|
ae = (byte*)&c + o;
|
||||||
sendchan(c, ae, nil);
|
chansend(c, ae, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
// chansend2(hchan *chan any, elem any) (pres bool);
|
// chansend2(hchan *chan any, elem any) (pres bool);
|
||||||
@ -396,7 +400,7 @@ sys·chansend2(Hchan* c, ...)
|
|||||||
o = rnd(o+c->elemsize, Structrnd);
|
o = rnd(o+c->elemsize, Structrnd);
|
||||||
ap = (byte*)&c + o;
|
ap = (byte*)&c + o;
|
||||||
|
|
||||||
sendchan(c, ae, ap);
|
chansend(c, ae, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// chanrecv1(hchan *chan any) (elem any);
|
// chanrecv1(hchan *chan any) (elem any);
|
||||||
|
@ -49,3 +49,27 @@ func makemap(typ *byte) (map *byte) {
|
|||||||
|
|
||||||
map = (byte*)makemap(t->key->size, t->elem->size, t->key->alg, t->elem->alg, 0);
|
map = (byte*)makemap(t->key->size, t->elem->size, t->key->alg, t->elem->alg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go wrappers around the C functions in chan.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
func makechan(typ *byte, size uint32) (ch *byte) {
|
||||||
|
ChanType *t;
|
||||||
|
|
||||||
|
// typ is a *runtime.ChanType, but the ChanType
|
||||||
|
// defined in type.h includes an interface value header
|
||||||
|
// in front of the raw ChanType. the -2 below backs up
|
||||||
|
// to the interface value header.
|
||||||
|
t = (ChanType*)((void**)typ - 2);
|
||||||
|
ch = (byte*)makechan(t->elem->size, t->elem->alg, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
func chansend(ch *byte, val *byte, pres *bool) {
|
||||||
|
chansend((Hchan*)ch, val, pres);
|
||||||
|
}
|
||||||
|
|
||||||
|
func chanrecv(ch *byte, val *byte, pres *bool) {
|
||||||
|
chanrecv((Hchan*)ch, val, pres);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ typedef struct Eface Eface;
|
|||||||
typedef struct Type Type;
|
typedef struct Type Type;
|
||||||
typedef struct Defer Defer;
|
typedef struct Defer Defer;
|
||||||
typedef struct hash Hmap;
|
typedef struct hash Hmap;
|
||||||
|
typedef struct Hchan Hchan;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* per cpu declaration
|
* per cpu declaration
|
||||||
@ -458,6 +459,7 @@ float64 ldexp(float64 d, int32 e);
|
|||||||
float64 modf(float64 d, float64 *ip);
|
float64 modf(float64 d, float64 *ip);
|
||||||
void semacquire(uint32*);
|
void semacquire(uint32*);
|
||||||
void semrelease(uint32*);
|
void semrelease(uint32*);
|
||||||
|
|
||||||
void mapassign(Hmap*, byte*, byte*);
|
void mapassign(Hmap*, byte*, byte*);
|
||||||
void mapaccess(Hmap*, byte*, byte*, bool*);
|
void mapaccess(Hmap*, byte*, byte*, bool*);
|
||||||
struct hash_iter* mapiterinit(Hmap*);
|
struct hash_iter* mapiterinit(Hmap*);
|
||||||
@ -465,3 +467,7 @@ void mapiternext(struct hash_iter*);
|
|||||||
bool mapiterkey(struct hash_iter*, void*);
|
bool mapiterkey(struct hash_iter*, void*);
|
||||||
void mapiterkeyvalue(struct hash_iter*, void*, void*);
|
void mapiterkeyvalue(struct hash_iter*, void*, void*);
|
||||||
Hmap* makemap(uint32, uint32, uint32, uint32, uint32);
|
Hmap* makemap(uint32, uint32, uint32, uint32, uint32);
|
||||||
|
|
||||||
|
Hchan* makechan(uint32, uint32, uint32);
|
||||||
|
void chansend(Hchan*, void*, bool*);
|
||||||
|
void chanrecv(Hchan*, void*, bool*);
|
||||||
|
@ -12,6 +12,7 @@ typedef struct InterfaceType InterfaceType;
|
|||||||
typedef struct Method Method;
|
typedef struct Method Method;
|
||||||
typedef struct IMethod IMethod;
|
typedef struct IMethod IMethod;
|
||||||
typedef struct MapType MapType;
|
typedef struct MapType MapType;
|
||||||
|
typedef struct ChanType ChanType;
|
||||||
|
|
||||||
struct CommonType
|
struct CommonType
|
||||||
{
|
{
|
||||||
@ -71,3 +72,10 @@ struct MapType
|
|||||||
Type *key;
|
Type *key;
|
||||||
Type *elem;
|
Type *elem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ChanType
|
||||||
|
{
|
||||||
|
Type;
|
||||||
|
Type *elem;
|
||||||
|
uintptr dir;
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user