mirror of
https://github.com/golang/go
synced 2024-10-06 08:00:07 +00:00
gc: implement nil chan support
The spec has defined nil chans this way for months. I'm behind. R=ken2 CC=golang-dev https://golang.org/cl/4897050
This commit is contained in:
parent
65bde087ae
commit
3770b0e60c
|
@ -66,15 +66,14 @@ char *runtimeimport =
|
||||||
"func \"\".mapiternext (hiter *any)\n"
|
"func \"\".mapiternext (hiter *any)\n"
|
||||||
"func \"\".mapiter1 (hiter *any) any\n"
|
"func \"\".mapiter1 (hiter *any) any\n"
|
||||||
"func \"\".mapiter2 (hiter *any) (key any, val any)\n"
|
"func \"\".mapiter2 (hiter *any) (key any, val any)\n"
|
||||||
"func \"\".makechan (elem *uint8, hint int64) chan any\n"
|
"func \"\".makechan (chanType *uint8, hint int64) chan any\n"
|
||||||
"func \"\".chanrecv1 (hchan <-chan any) any\n"
|
"func \"\".chanrecv1 (chanType *uint8, hchan <-chan any) any\n"
|
||||||
"func \"\".chanrecv2 (hchan <-chan any) (elem any, received bool)\n"
|
"func \"\".chanrecv2 (chanType *uint8, hchan <-chan any) (elem any, received bool)\n"
|
||||||
"func \"\".chansend1 (hchan chan<- any, elem any)\n"
|
"func \"\".chansend1 (chanType *uint8, hchan chan<- any, elem any)\n"
|
||||||
"func \"\".closechan (hchan any)\n"
|
"func \"\".closechan (hchan any)\n"
|
||||||
"func \"\".closedchan (hchan any) bool\n"
|
"func \"\".selectnbsend (chanType *uint8, hchan chan<- any, elem any) bool\n"
|
||||||
"func \"\".selectnbsend (hchan chan<- any, elem any) bool\n"
|
"func \"\".selectnbrecv (chanType *uint8, elem *any, hchan <-chan any) bool\n"
|
||||||
"func \"\".selectnbrecv (elem *any, hchan <-chan any) bool\n"
|
"func \"\".selectnbrecv2 (chanType *uint8, elem *any, received *bool, hchan <-chan any) bool\n"
|
||||||
"func \"\".selectnbrecv2 (elem *any, received *bool, hchan <-chan any) bool\n"
|
|
||||||
"func \"\".newselect (size int) *uint8\n"
|
"func \"\".newselect (size int) *uint8\n"
|
||||||
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n"
|
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n"
|
||||||
"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
|
"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
|
||||||
|
|
|
@ -91,16 +91,15 @@ func mapiter1(hiter *any) (key any)
|
||||||
func mapiter2(hiter *any) (key any, val any)
|
func mapiter2(hiter *any) (key any, val any)
|
||||||
|
|
||||||
// *byte is really *runtime.Type
|
// *byte is really *runtime.Type
|
||||||
func makechan(elem *byte, hint int64) (hchan chan any)
|
func makechan(chanType *byte, hint int64) (hchan chan any)
|
||||||
func chanrecv1(hchan <-chan any) (elem any)
|
func chanrecv1(chanType *byte, hchan <-chan any) (elem any)
|
||||||
func chanrecv2(hchan <-chan any) (elem any, received bool)
|
func chanrecv2(chanType *byte, hchan <-chan any) (elem any, received bool)
|
||||||
func chansend1(hchan chan<- any, elem any)
|
func chansend1(chanType *byte, hchan chan<- any, elem any)
|
||||||
func closechan(hchan any)
|
func closechan(hchan any)
|
||||||
func closedchan(hchan any) bool
|
|
||||||
|
|
||||||
func selectnbsend(hchan chan<- any, elem any) bool
|
func selectnbsend(chanType *byte, hchan chan<- any, elem any) bool
|
||||||
func selectnbrecv(elem *any, hchan <-chan any) bool
|
func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool
|
||||||
func selectnbrecv2(elem *any, received *bool, hchan <-chan any) bool
|
func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool
|
||||||
|
|
||||||
func newselect(size int) (sel *byte)
|
func newselect(size int) (sel *byte)
|
||||||
func selectsend(sel *byte, hchan chan<- any, elem *any) (selected bool)
|
func selectsend(sel *byte, hchan chan<- any, elem *any) (selected bool)
|
||||||
|
|
|
@ -250,9 +250,8 @@ walkselect(Node *sel)
|
||||||
case OSEND:
|
case OSEND:
|
||||||
// if c != nil && selectnbsend(c, v) { body } else { default body }
|
// if c != nil && selectnbsend(c, v) { body } else { default body }
|
||||||
ch = cheapexpr(n->left, &r->ninit);
|
ch = cheapexpr(n->left, &r->ninit);
|
||||||
r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()),
|
r->ntest = mkcall1(chanfn("selectnbsend", 2, ch->type),
|
||||||
mkcall1(chanfn("selectnbsend", 2, ch->type),
|
types[TBOOL], &r->ninit, typename(ch->type), ch, n->right);
|
||||||
types[TBOOL], &r->ninit, ch, n->right));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSELRECV:
|
case OSELRECV:
|
||||||
|
@ -260,9 +259,8 @@ walkselect(Node *sel)
|
||||||
r = nod(OIF, N, N);
|
r = nod(OIF, N, N);
|
||||||
r->ninit = cas->ninit;
|
r->ninit = cas->ninit;
|
||||||
ch = cheapexpr(n->right->left, &r->ninit);
|
ch = cheapexpr(n->right->left, &r->ninit);
|
||||||
r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()),
|
r->ntest = mkcall1(chanfn("selectnbrecv", 2, ch->type),
|
||||||
mkcall1(chanfn("selectnbrecv", 2, ch->type),
|
types[TBOOL], &r->ninit, typename(ch->type), n->left, ch);
|
||||||
types[TBOOL], &r->ninit, n->left, ch));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSELRECV2:
|
case OSELRECV2:
|
||||||
|
@ -270,9 +268,8 @@ walkselect(Node *sel)
|
||||||
r = nod(OIF, N, N);
|
r = nod(OIF, N, N);
|
||||||
r->ninit = cas->ninit;
|
r->ninit = cas->ninit;
|
||||||
ch = cheapexpr(n->right->left, &r->ninit);
|
ch = cheapexpr(n->right->left, &r->ninit);
|
||||||
r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()),
|
r->ntest = mkcall1(chanfn("selectnbrecv2", 2, ch->type),
|
||||||
mkcall1(chanfn("selectnbrecv2", 2, ch->type),
|
types[TBOOL], &r->ninit, typename(ch->type), n->left, n->ntest, ch);
|
||||||
types[TBOOL], &r->ninit, n->left, n->ntest, ch));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
typecheck(&r->ntest, Erv);
|
typecheck(&r->ntest, Erv);
|
||||||
|
|
|
@ -591,7 +591,7 @@ walkexpr(Node **np, NodeList **init)
|
||||||
walkexprlistsafe(n->list, init);
|
walkexprlistsafe(n->list, init);
|
||||||
walkexpr(&r->left, init);
|
walkexpr(&r->left, init);
|
||||||
fn = chanfn("chanrecv2", 2, r->left->type);
|
fn = chanfn("chanrecv2", 2, r->left->type);
|
||||||
r = mkcall1(fn, getoutargx(fn->type), init, r->left);
|
r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left);
|
||||||
n->rlist->n = r;
|
n->rlist->n = r;
|
||||||
n->op = OAS2FUNC;
|
n->op = OAS2FUNC;
|
||||||
goto as2func;
|
goto as2func;
|
||||||
|
@ -858,7 +858,7 @@ walkexpr(Node **np, NodeList **init)
|
||||||
case ORECV:
|
case ORECV:
|
||||||
walkexpr(&n->left, init);
|
walkexpr(&n->left, init);
|
||||||
walkexpr(&n->right, init);
|
walkexpr(&n->right, init);
|
||||||
n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, n->left);
|
n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, typename(n->left->type), n->left);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OSLICE:
|
case OSLICE:
|
||||||
|
@ -1078,7 +1078,7 @@ walkexpr(Node **np, NodeList **init)
|
||||||
|
|
||||||
case OMAKECHAN:
|
case OMAKECHAN:
|
||||||
n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
|
n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
|
||||||
typename(n->type->type),
|
typename(n->type),
|
||||||
conv(n->left, types[TINT64]));
|
conv(n->left, types[TINT64]));
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
|
@ -1163,7 +1163,7 @@ walkexpr(Node **np, NodeList **init)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OSEND:
|
case OSEND:
|
||||||
n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, n->left, n->right);
|
n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n->right);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCLOSURE:
|
case OCLOSURE:
|
||||||
|
|
|
@ -1162,7 +1162,7 @@ func (iv internalValue) recv(nb bool) (val Value, ok bool) {
|
||||||
if ch == 0 {
|
if ch == 0 {
|
||||||
panic("recv on nil channel")
|
panic("recv on nil channel")
|
||||||
}
|
}
|
||||||
valWord, selected, ok := chanrecv(ch, nb)
|
valWord, selected, ok := chanrecv(iv.typ.runtimeType(), ch, nb)
|
||||||
if selected {
|
if selected {
|
||||||
val = valueFromIword(0, t.Elem(), valWord)
|
val = valueFromIword(0, t.Elem(), valWord)
|
||||||
}
|
}
|
||||||
|
@ -1192,7 +1192,7 @@ func (iv internalValue) send(x Value, nb bool) (selected bool) {
|
||||||
if ch == 0 {
|
if ch == 0 {
|
||||||
panic("send on nil channel")
|
panic("send on nil channel")
|
||||||
}
|
}
|
||||||
return chansend(ch, ix.word, nb)
|
return chansend(iv.typ.runtimeType(), ch, ix.word, nb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set assigns x to the value v.
|
// Set assigns x to the value v.
|
||||||
|
@ -1720,8 +1720,8 @@ func convertForAssignment(what string, addr unsafe.Pointer, dst Type, iv interna
|
||||||
func chancap(ch iword) int32
|
func chancap(ch iword) int32
|
||||||
func chanclose(ch iword)
|
func chanclose(ch iword)
|
||||||
func chanlen(ch iword) int32
|
func chanlen(ch iword) int32
|
||||||
func chanrecv(ch iword, nb bool) (val iword, selected, received bool)
|
func chanrecv(t *runtime.Type, ch iword, nb bool) (val iword, selected, received bool)
|
||||||
func chansend(ch iword, val iword, nb bool) bool
|
func chansend(t *runtime.Type, ch iword, val iword, nb bool) bool
|
||||||
|
|
||||||
func makechan(typ *runtime.Type, size uint32) (ch iword)
|
func makechan(typ *runtime.Type, size uint32) (ch iword)
|
||||||
func makemap(t *runtime.Type) iword
|
func makemap(t *runtime.Type) iword
|
||||||
|
|
|
@ -81,10 +81,13 @@ static void enqueue(WaitQ*, SudoG*);
|
||||||
static void destroychan(Hchan*);
|
static void destroychan(Hchan*);
|
||||||
|
|
||||||
Hchan*
|
Hchan*
|
||||||
runtime·makechan_c(Type *elem, int64 hint)
|
runtime·makechan_c(ChanType *t, int64 hint)
|
||||||
{
|
{
|
||||||
Hchan *c;
|
Hchan *c;
|
||||||
int32 n;
|
int32 n;
|
||||||
|
Type *elem;
|
||||||
|
|
||||||
|
elem = t->elem;
|
||||||
|
|
||||||
if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
|
if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
|
||||||
runtime·panicstring("makechan: size out of range");
|
runtime·panicstring("makechan: size out of range");
|
||||||
|
@ -121,7 +124,7 @@ runtime·makechan_c(Type *elem, int64 hint)
|
||||||
void
|
void
|
||||||
reflect·makechan(ChanType *t, uint32 size, Hchan *c)
|
reflect·makechan(ChanType *t, uint32 size, Hchan *c)
|
||||||
{
|
{
|
||||||
c = runtime·makechan_c(t->elem, size);
|
c = runtime·makechan_c(t, size);
|
||||||
FLUSH(&c);
|
FLUSH(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,11 +135,11 @@ destroychan(Hchan *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// makechan(elem *Type, hint int64) (hchan *chan any);
|
// makechan(t *ChanType, hint int64) (hchan *chan any);
|
||||||
void
|
void
|
||||||
runtime·makechan(Type *elem, int64 hint, Hchan *ret)
|
runtime·makechan(ChanType *t, int64 hint, Hchan *ret)
|
||||||
{
|
{
|
||||||
ret = runtime·makechan_c(elem, hint);
|
ret = runtime·makechan_c(t, hint);
|
||||||
FLUSH(&ret);
|
FLUSH(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,14 +158,22 @@ runtime·makechan(Type *elem, int64 hint, Hchan *ret)
|
||||||
* the operation; we'll see that it's now closed.
|
* the operation; we'll see that it's now closed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
runtime·chansend(Hchan *c, byte *ep, bool *pres)
|
runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
|
||||||
{
|
{
|
||||||
SudoG *sg;
|
SudoG *sg;
|
||||||
SudoG mysg;
|
SudoG mysg;
|
||||||
G* gp;
|
G* gp;
|
||||||
|
|
||||||
if(c == nil)
|
if(c == nil) {
|
||||||
runtime·panicstring("send to nil channel");
|
USED(t);
|
||||||
|
if(pres != nil) {
|
||||||
|
*pres = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g->status = Gwaiting;
|
||||||
|
runtime·gosched();
|
||||||
|
return; // not reached
|
||||||
|
}
|
||||||
|
|
||||||
if(runtime·gcwaiting)
|
if(runtime·gcwaiting)
|
||||||
runtime·gosched();
|
runtime·gosched();
|
||||||
|
@ -263,21 +274,29 @@ closed:
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
runtime·chanrecv(Hchan* c, byte *ep, bool *selected, bool *received)
|
runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received)
|
||||||
{
|
{
|
||||||
SudoG *sg;
|
SudoG *sg;
|
||||||
SudoG mysg;
|
SudoG mysg;
|
||||||
G *gp;
|
G *gp;
|
||||||
|
|
||||||
if(c == nil)
|
|
||||||
runtime·panicstring("receive from nil channel");
|
|
||||||
|
|
||||||
if(runtime·gcwaiting)
|
if(runtime·gcwaiting)
|
||||||
runtime·gosched();
|
runtime·gosched();
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
runtime·printf("chanrecv: chan=%p\n", c);
|
runtime·printf("chanrecv: chan=%p\n", c);
|
||||||
|
|
||||||
|
if(c == nil) {
|
||||||
|
USED(t);
|
||||||
|
if(selected != nil) {
|
||||||
|
*selected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g->status = Gwaiting;
|
||||||
|
runtime·gosched();
|
||||||
|
return; // not reached
|
||||||
|
}
|
||||||
|
|
||||||
runtime·lock(c);
|
runtime·lock(c);
|
||||||
if(c->dataqsiz > 0)
|
if(c->dataqsiz > 0)
|
||||||
goto asynch;
|
goto asynch;
|
||||||
|
@ -385,50 +404,29 @@ closed:
|
||||||
// chansend1(hchan *chan any, elem any);
|
// chansend1(hchan *chan any, elem any);
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·chansend1(Hchan* c, ...)
|
runtime·chansend1(ChanType *t, Hchan* c, ...)
|
||||||
{
|
{
|
||||||
int32 o;
|
runtime·chansend(t, c, (byte*)(&c+1), nil);
|
||||||
byte *ae;
|
|
||||||
|
|
||||||
if(c == nil)
|
|
||||||
runtime·panicstring("send to nil channel");
|
|
||||||
|
|
||||||
o = runtime·rnd(sizeof(c), c->elemalign);
|
|
||||||
ae = (byte*)&c + o;
|
|
||||||
runtime·chansend(c, ae, nil);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// chanrecv1(hchan *chan any) (elem any);
|
// chanrecv1(hchan *chan any) (elem any);
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·chanrecv1(Hchan* c, ...)
|
runtime·chanrecv1(ChanType *t, Hchan* c, ...)
|
||||||
{
|
{
|
||||||
int32 o;
|
runtime·chanrecv(t, c, (byte*)(&c+1), nil, nil);
|
||||||
byte *ae;
|
|
||||||
|
|
||||||
o = runtime·rnd(sizeof(c), Structrnd);
|
|
||||||
ae = (byte*)&c + o;
|
|
||||||
|
|
||||||
runtime·chanrecv(c, ae, nil, nil);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// chanrecv2(hchan *chan any) (elem any, received bool);
|
// chanrecv2(hchan *chan any) (elem any, received bool);
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·chanrecv2(Hchan* c, ...)
|
runtime·chanrecv2(ChanType *t, Hchan* c, ...)
|
||||||
{
|
{
|
||||||
int32 o;
|
byte *ae, *ap;
|
||||||
byte *ae, *ac;
|
|
||||||
|
|
||||||
if(c == nil)
|
ae = (byte*)(&c+1);
|
||||||
runtime·panicstring("receive from nil channel");
|
ap = ae + t->elem->size;
|
||||||
|
runtime·chanrecv(t, c, ae, nil, ap);
|
||||||
o = runtime·rnd(sizeof(c), Structrnd);
|
|
||||||
ae = (byte*)&c + o;
|
|
||||||
o += c->elemsize;
|
|
||||||
ac = (byte*)&c + o;
|
|
||||||
|
|
||||||
runtime·chanrecv(c, ae, nil, ac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// func selectnbsend(c chan any, elem any) bool
|
// func selectnbsend(c chan any, elem any) bool
|
||||||
|
@ -444,7 +442,7 @@ runtime·chanrecv2(Hchan* c, ...)
|
||||||
//
|
//
|
||||||
// as
|
// as
|
||||||
//
|
//
|
||||||
// if c != nil && selectnbsend(c, v) {
|
// if selectnbsend(c, v) {
|
||||||
// ... foo
|
// ... foo
|
||||||
// } else {
|
// } else {
|
||||||
// ... bar
|
// ... bar
|
||||||
|
@ -452,17 +450,13 @@ runtime·chanrecv2(Hchan* c, ...)
|
||||||
//
|
//
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·selectnbsend(Hchan *c, ...)
|
runtime·selectnbsend(ChanType *t, Hchan *c, ...)
|
||||||
{
|
{
|
||||||
int32 o;
|
|
||||||
byte *ae, *ap;
|
byte *ae, *ap;
|
||||||
|
|
||||||
o = runtime·rnd(sizeof(c), c->elemalign);
|
ae = (byte*)(&c + 1);
|
||||||
ae = (byte*)&c + o;
|
ap = ae + runtime·rnd(t->elem->size, Structrnd);
|
||||||
o = runtime·rnd(o+c->elemsize, Structrnd);
|
runtime·chansend(t, c, ae, ap);
|
||||||
ap = (byte*)&c + o;
|
|
||||||
|
|
||||||
runtime·chansend(c, ae, ap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// func selectnbrecv(elem *any, c chan any) bool
|
// func selectnbrecv(elem *any, c chan any) bool
|
||||||
|
@ -478,7 +472,7 @@ runtime·selectnbsend(Hchan *c, ...)
|
||||||
//
|
//
|
||||||
// as
|
// as
|
||||||
//
|
//
|
||||||
// if c != nil && selectnbrecv(&v, c) {
|
// if selectnbrecv(&v, c) {
|
||||||
// ... foo
|
// ... foo
|
||||||
// } else {
|
// } else {
|
||||||
// ... bar
|
// ... bar
|
||||||
|
@ -486,9 +480,9 @@ runtime·selectnbsend(Hchan *c, ...)
|
||||||
//
|
//
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·selectnbrecv(byte *v, Hchan *c, bool selected)
|
runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected)
|
||||||
{
|
{
|
||||||
runtime·chanrecv(c, v, &selected, nil);
|
runtime·chanrecv(t, c, v, &selected, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
|
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
|
||||||
|
@ -512,9 +506,9 @@ runtime·selectnbrecv(byte *v, Hchan *c, bool selected)
|
||||||
//
|
//
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected)
|
runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected)
|
||||||
{
|
{
|
||||||
runtime·chanrecv(c, v, &selected, received);
|
runtime·chanrecv(t, c, v, &selected, received);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For reflect:
|
// For reflect:
|
||||||
|
@ -525,14 +519,11 @@ runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected)
|
||||||
// The "uintptr selected" is really "bool selected" but saying
|
// The "uintptr selected" is really "bool selected" but saying
|
||||||
// uintptr gets us the right alignment for the output parameter block.
|
// uintptr gets us the right alignment for the output parameter block.
|
||||||
void
|
void
|
||||||
reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected)
|
reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
|
||||||
{
|
{
|
||||||
bool *sp;
|
bool *sp;
|
||||||
byte *vp;
|
byte *vp;
|
||||||
|
|
||||||
if(c == nil)
|
|
||||||
runtime·panicstring("send to nil channel");
|
|
||||||
|
|
||||||
if(nb) {
|
if(nb) {
|
||||||
selected = false;
|
selected = false;
|
||||||
sp = (bool*)&selected;
|
sp = (bool*)&selected;
|
||||||
|
@ -541,11 +532,11 @@ reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected)
|
||||||
FLUSH(&selected);
|
FLUSH(&selected);
|
||||||
sp = nil;
|
sp = nil;
|
||||||
}
|
}
|
||||||
if(c->elemsize <= sizeof(val))
|
if(t->elem->size <= sizeof(val))
|
||||||
vp = (byte*)&val;
|
vp = (byte*)&val;
|
||||||
else
|
else
|
||||||
vp = (byte*)val;
|
vp = (byte*)val;
|
||||||
runtime·chansend(c, vp, sp);
|
runtime·chansend(t, c, vp, sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For reflect:
|
// For reflect:
|
||||||
|
@ -553,14 +544,11 @@ reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected)
|
||||||
// where an iword is the same word an interface value would use:
|
// where an iword is the same word an interface value would use:
|
||||||
// the actual data if it fits, or else a pointer to the data.
|
// the actual data if it fits, or else a pointer to the data.
|
||||||
void
|
void
|
||||||
reflect·chanrecv(Hchan *c, bool nb, uintptr val, bool selected, bool received)
|
reflect·chanrecv(ChanType *t, Hchan *c, bool nb, uintptr val, bool selected, bool received)
|
||||||
{
|
{
|
||||||
byte *vp;
|
byte *vp;
|
||||||
bool *sp;
|
bool *sp;
|
||||||
|
|
||||||
if(c == nil)
|
|
||||||
runtime·panicstring("receive from nil channel");
|
|
||||||
|
|
||||||
if(nb) {
|
if(nb) {
|
||||||
selected = false;
|
selected = false;
|
||||||
sp = &selected;
|
sp = &selected;
|
||||||
|
@ -571,15 +559,15 @@ reflect·chanrecv(Hchan *c, bool nb, uintptr val, bool selected, bool received)
|
||||||
}
|
}
|
||||||
received = false;
|
received = false;
|
||||||
FLUSH(&received);
|
FLUSH(&received);
|
||||||
if(c->elemsize <= sizeof(val)) {
|
if(t->elem->size <= sizeof(val)) {
|
||||||
val = 0;
|
val = 0;
|
||||||
vp = (byte*)&val;
|
vp = (byte*)&val;
|
||||||
} else {
|
} else {
|
||||||
vp = runtime·mal(c->elemsize);
|
vp = runtime·mal(t->elem->size);
|
||||||
val = (uintptr)vp;
|
val = (uintptr)vp;
|
||||||
FLUSH(&val);
|
FLUSH(&val);
|
||||||
}
|
}
|
||||||
runtime·chanrecv(c, vp, sp, &received);
|
runtime·chanrecv(t, c, vp, sp, &received);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newselect(int32, Select**);
|
static void newselect(int32, Select**);
|
||||||
|
|
|
@ -62,6 +62,7 @@ typedef struct Iface Iface;
|
||||||
typedef struct Itab Itab;
|
typedef struct Itab Itab;
|
||||||
typedef struct Eface Eface;
|
typedef struct Eface Eface;
|
||||||
typedef struct Type Type;
|
typedef struct Type Type;
|
||||||
|
typedef struct ChanType ChanType;
|
||||||
typedef struct MapType MapType;
|
typedef struct MapType MapType;
|
||||||
typedef struct Defer Defer;
|
typedef struct Defer Defer;
|
||||||
typedef struct Panic Panic;
|
typedef struct Panic Panic;
|
||||||
|
@ -624,9 +625,9 @@ bool runtime·mapiterkey(struct hash_iter*, void*);
|
||||||
void runtime·mapiterkeyvalue(struct hash_iter*, void*, void*);
|
void runtime·mapiterkeyvalue(struct hash_iter*, void*, void*);
|
||||||
Hmap* runtime·makemap_c(MapType*, int64);
|
Hmap* runtime·makemap_c(MapType*, int64);
|
||||||
|
|
||||||
Hchan* runtime·makechan_c(Type*, int64);
|
Hchan* runtime·makechan_c(ChanType*, int64);
|
||||||
void runtime·chansend(Hchan*, void*, bool*);
|
void runtime·chansend(ChanType*, Hchan*, void*, bool*);
|
||||||
void runtime·chanrecv(Hchan*, void*, bool*, bool*);
|
void runtime·chanrecv(ChanType*, Hchan*, void*, bool*, bool*);
|
||||||
int32 runtime·chanlen(Hchan*);
|
int32 runtime·chanlen(Hchan*);
|
||||||
int32 runtime·chancap(Hchan*);
|
int32 runtime·chancap(Hchan*);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ typedef struct UncommonType UncommonType;
|
||||||
typedef struct InterfaceType InterfaceType;
|
typedef struct InterfaceType InterfaceType;
|
||||||
typedef struct Method Method;
|
typedef struct Method Method;
|
||||||
typedef struct IMethod IMethod;
|
typedef struct IMethod IMethod;
|
||||||
typedef struct ChanType ChanType;
|
|
||||||
typedef struct SliceType SliceType;
|
typedef struct SliceType SliceType;
|
||||||
typedef struct FuncType FuncType;
|
typedef struct FuncType FuncType;
|
||||||
|
|
||||||
|
|
|
@ -58,15 +58,15 @@ func main() {
|
||||||
closedch := make(chan int)
|
closedch := make(chan int)
|
||||||
close(closedch)
|
close(closedch)
|
||||||
|
|
||||||
// sending/receiving from a nil channel outside a select panics
|
// sending/receiving from a nil channel blocks
|
||||||
testPanic(always, func() {
|
testBlock(always, func() {
|
||||||
nilch <- 7
|
nilch <- 7
|
||||||
})
|
})
|
||||||
testPanic(always, func() {
|
testBlock(always, func() {
|
||||||
<-nilch
|
<-nilch
|
||||||
})
|
})
|
||||||
|
|
||||||
// sending/receiving from a nil channel inside a select never panics
|
// sending/receiving from a nil channel inside a select is never selected
|
||||||
testPanic(never, func() {
|
testPanic(never, func() {
|
||||||
select {
|
select {
|
||||||
case nilch <- 7:
|
case nilch <- 7:
|
||||||
|
|
Loading…
Reference in a new issue