}
}
-func TestMapAccess(t *testing.T) {
+func TestMap(t *testing.T) {
m := map[string]int{ "a": 1, "b": 2 };
mv := NewValue(m).(*MapValue);
if n := mv.Len(); n != len(m) {
t.Errorf("newm[%q] = %d, but m[%q] = %d, %v", k, v, k, mv, ok);
}
}
-
+
newmap.Put(NewValue("a"), nil);
v, ok := newm["a"];
if ok {
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");
+ }
+}
+
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.
func (v *ChanValue) Send(x Value) {
- panic("unimplemented: channel Send");
+ v.send(x, nil);
}
// Recv receives and returns a value from the channel v.
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.
// It returns true if the value was sent, false otherwise.
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.
// It returns the value if one is received, nil otherwise.
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;
}
/*
return a[0:i];
}
+// MakeMap creates a new map of the specified type.
func MakeMap(typ *MapType) *MapValue {
v := MakeZero(typ).(*MapValue);
*(**byte)(v.addr) = makemap((*runtime.MapType)(unsafe.Pointer(typ)));
Emax = 0x0800, // error limit before throw
};
-typedef struct Hchan Hchan;
typedef struct Link Link;
typedef struct WaitQ WaitQ;
typedef struct SudoG SudoG;
static uint32 fastrand1(void);
static uint32 fastrand2(void);
-// newchan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any);
-void
-sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint,
- Hchan* ret)
+Hchan*
+makechan(uint32 elemsize, uint32 elemalg, uint32 hint)
{
Hchan *c;
int32 i;
c->dataqsiz = hint;
}
- ret = c;
- FLUSH(&ret);
-
if(debug) {
prints("newchan: chan=");
sys·printpointer(c);
sys·printint(c->dataqsiz);
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
* not complete
*/
void
-sendchan(Hchan *c, byte *ep, bool *pres)
+chansend(Hchan *c, byte *ep, bool *pres)
{
SudoG *sg;
G* gp;
unlock(&chanlock);
}
-static void
+void
chanrecv(Hchan* c, byte *ep, bool* pres)
{
SudoG *sg;
o = rnd(sizeof(c), c->elemsize);
ae = (byte*)&c + o;
- sendchan(c, ae, nil);
+ chansend(c, ae, nil);
}
// chansend2(hchan *chan any, elem any) (pres bool);
o = rnd(o+c->elemsize, Structrnd);
ap = (byte*)&c + o;
- sendchan(c, ae, ap);
+ chansend(c, ae, ap);
}
// chanrecv1(hchan *chan any) (elem any);
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);
+}
+
typedef struct Type Type;
typedef struct Defer Defer;
typedef struct hash Hmap;
+typedef struct Hchan Hchan;
/*
* per cpu declaration
float64 modf(float64 d, float64 *ip);
void semacquire(uint32*);
void semrelease(uint32*);
+
void mapassign(Hmap*, byte*, byte*);
void mapaccess(Hmap*, byte*, byte*, bool*);
struct hash_iter* mapiterinit(Hmap*);
bool mapiterkey(struct hash_iter*, void*);
void mapiterkeyvalue(struct hash_iter*, void*, void*);
Hmap* makemap(uint32, uint32, uint32, uint32, uint32);
+
+Hchan* makechan(uint32, uint32, uint32);
+void chansend(Hchan*, void*, bool*);
+void chanrecv(Hchan*, void*, bool*);
typedef struct Method Method;
typedef struct IMethod IMethod;
typedef struct MapType MapType;
+typedef struct ChanType ChanType;
struct CommonType
{
Type *key;
Type *elem;
};
+
+struct ChanType
+{
+ Type;
+ Type *elem;
+ uintptr dir;
+};