mirror of
https://github.com/golang/go
synced 2024-11-22 07:04:40 -07:00
gc, runtime: replace closed(c) with x, ok := <-c
R=ken2, ken3 CC=golang-dev https://golang.org/cl/4259064
This commit is contained in:
parent
9f2cb86fe2
commit
8bf34e3356
@ -66,15 +66,17 @@ char *runtimeimport =
|
|||||||
"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 (elem *uint8, hint int64) chan any\n"
|
||||||
"func \"\".chanrecv1 (hchan <-chan any) any\n"
|
"func \"\".chanrecv1 (hchan <-chan any) any\n"
|
||||||
"func \"\".chanrecv3 (hchan <-chan any) (elem any, closed bool)\n"
|
"func \"\".chanrecv2 (hchan <-chan any) (elem any, received bool)\n"
|
||||||
"func \"\".chansend1 (hchan chan<- any, elem any)\n"
|
"func \"\".chansend1 (hchan chan<- any, elem any)\n"
|
||||||
"func \"\".closechan (hchan any)\n"
|
"func \"\".closechan (hchan any)\n"
|
||||||
"func \"\".closedchan (hchan any) bool\n"
|
"func \"\".closedchan (hchan any) bool\n"
|
||||||
"func \"\".selectnbsend (hchan chan<- any, elem any) bool\n"
|
"func \"\".selectnbsend (hchan chan<- any, elem any) bool\n"
|
||||||
"func \"\".selectnbrecv (elem *any, hchan <-chan any) bool\n"
|
"func \"\".selectnbrecv (elem *any, 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"
|
||||||
|
"func \"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n"
|
||||||
"func \"\".selectdefault (sel *uint8) bool\n"
|
"func \"\".selectdefault (sel *uint8) bool\n"
|
||||||
"func \"\".selectgo (sel *uint8)\n"
|
"func \"\".selectgo (sel *uint8)\n"
|
||||||
"func \"\".block ()\n"
|
"func \"\".block ()\n"
|
||||||
|
@ -356,12 +356,11 @@ enum
|
|||||||
OARRAY,
|
OARRAY,
|
||||||
OARRAYBYTESTR, OARRAYRUNESTR,
|
OARRAYBYTESTR, OARRAYRUNESTR,
|
||||||
OSTRARRAYBYTE, OSTRARRAYRUNE,
|
OSTRARRAYBYTE, OSTRARRAYRUNE,
|
||||||
OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECVCLOSED, OAS2MAPR, OAS2DOTTYPE, OASOP,
|
OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE, OASOP,
|
||||||
OBAD,
|
OBAD,
|
||||||
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
|
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
|
||||||
OCAP,
|
OCAP,
|
||||||
OCLOSE,
|
OCLOSE,
|
||||||
OCLOSED,
|
|
||||||
OCLOSURE,
|
OCLOSURE,
|
||||||
OCMPIFACE, OCMPSTR,
|
OCMPIFACE, OCMPSTR,
|
||||||
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
|
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
|
||||||
@ -389,6 +388,7 @@ enum
|
|||||||
ORECV,
|
ORECV,
|
||||||
ORUNESTR,
|
ORUNESTR,
|
||||||
OSELRECV,
|
OSELRECV,
|
||||||
|
OSELRECV2,
|
||||||
OIOTA,
|
OIOTA,
|
||||||
OREAL, OIMAG, OCOMPLEX,
|
OREAL, OIMAG, OCOMPLEX,
|
||||||
|
|
||||||
|
@ -461,23 +461,32 @@ case:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
| LCASE expr '=' expr ':'
|
| LCASE expr_or_type_list '=' expr ':'
|
||||||
{
|
{
|
||||||
|
Node *n;
|
||||||
|
|
||||||
// will be converted to OCASE
|
// will be converted to OCASE
|
||||||
// right will point to next case
|
// right will point to next case
|
||||||
// done in casebody()
|
// done in casebody()
|
||||||
poptodcl();
|
poptodcl();
|
||||||
$$ = nod(OXCASE, N, N);
|
$$ = nod(OXCASE, N, N);
|
||||||
$$->list = list1(nod(OAS, $2, $4));
|
if($2->next == nil)
|
||||||
|
n = nod(OAS, $2->n, $4);
|
||||||
|
else {
|
||||||
|
n = nod(OAS2, N, N);
|
||||||
|
n->list = $2;
|
||||||
|
n->rlist = list1($4);
|
||||||
}
|
}
|
||||||
| LCASE name LCOLAS expr ':'
|
$$->list = list1(n);
|
||||||
|
}
|
||||||
|
| LCASE expr_or_type_list LCOLAS expr ':'
|
||||||
{
|
{
|
||||||
// will be converted to OCASE
|
// will be converted to OCASE
|
||||||
// right will point to next case
|
// right will point to next case
|
||||||
// done in casebody()
|
// done in casebody()
|
||||||
poptodcl();
|
poptodcl();
|
||||||
$$ = nod(OXCASE, N, N);
|
$$ = nod(OXCASE, N, N);
|
||||||
$$->list = list1(colas(list1($2), list1($4)));
|
$$->list = list1(colas($2, list1($4)));
|
||||||
}
|
}
|
||||||
| LDEFAULT ':'
|
| LDEFAULT ':'
|
||||||
{
|
{
|
||||||
|
@ -1555,7 +1555,6 @@ static struct
|
|||||||
"append", LNAME, Txxx, OAPPEND,
|
"append", LNAME, Txxx, OAPPEND,
|
||||||
"cap", LNAME, Txxx, OCAP,
|
"cap", LNAME, Txxx, OCAP,
|
||||||
"close", LNAME, Txxx, OCLOSE,
|
"close", LNAME, Txxx, OCLOSE,
|
||||||
"closed", LNAME, Txxx, OCLOSED,
|
|
||||||
"complex", LNAME, Txxx, OCOMPLEX,
|
"complex", LNAME, Txxx, OCOMPLEX,
|
||||||
"copy", LNAME, Txxx, OCOPY,
|
"copy", LNAME, Txxx, OCOPY,
|
||||||
"imag", LNAME, Txxx, OIMAG,
|
"imag", LNAME, Txxx, OIMAG,
|
||||||
|
@ -52,7 +52,6 @@ exprfmt(Fmt *f, Node *n, int prec)
|
|||||||
case OARRAYBYTESTR:
|
case OARRAYBYTESTR:
|
||||||
case OCAP:
|
case OCAP:
|
||||||
case OCLOSE:
|
case OCLOSE:
|
||||||
case OCLOSED:
|
|
||||||
case OCOPY:
|
case OCOPY:
|
||||||
case OLEN:
|
case OLEN:
|
||||||
case OMAKE:
|
case OMAKE:
|
||||||
@ -405,7 +404,6 @@ exprfmt(Fmt *f, Node *n, int prec)
|
|||||||
case OAPPEND:
|
case OAPPEND:
|
||||||
case OCAP:
|
case OCAP:
|
||||||
case OCLOSE:
|
case OCLOSE:
|
||||||
case OCLOSED:
|
|
||||||
case OLEN:
|
case OLEN:
|
||||||
case OCOPY:
|
case OCOPY:
|
||||||
case OMAKE:
|
case OMAKE:
|
||||||
|
@ -203,8 +203,8 @@ walkrange(Node *n)
|
|||||||
hb = nod(OXXX, N, N);
|
hb = nod(OXXX, N, N);
|
||||||
tempname(hb, types[TBOOL]);
|
tempname(hb, types[TBOOL]);
|
||||||
|
|
||||||
n->ntest = nod(ONOT, hb, N);
|
n->ntest = hb;
|
||||||
a = nod(OAS2RECVCLOSED, N, N);
|
a = nod(OAS2RECV, N, N);
|
||||||
a->typecheck = 1;
|
a->typecheck = 1;
|
||||||
a->list = list(list1(hv1), hb);
|
a->list = list(list1(hv1), hb);
|
||||||
a->rlist = list1(nod(ORECV, ha, N));
|
a->rlist = list1(nod(ORECV, ha, N));
|
||||||
|
@ -92,17 +92,19 @@ 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(elem *byte, hint int64) (hchan chan any)
|
||||||
func chanrecv1(hchan <-chan any) (elem any)
|
func chanrecv1(hchan <-chan any) (elem any)
|
||||||
func chanrecv3(hchan <-chan any) (elem any, closed bool)
|
func chanrecv2(hchan <-chan any) (elem any, received bool)
|
||||||
func chansend1(hchan chan<- any, elem any)
|
func chansend1(hchan chan<- any, elem any)
|
||||||
func closechan(hchan any)
|
func closechan(hchan any)
|
||||||
func closedchan(hchan any) bool
|
func closedchan(hchan any) bool
|
||||||
|
|
||||||
func selectnbsend(hchan chan<- any, elem any) bool
|
func selectnbsend(hchan chan<- any, elem any) bool
|
||||||
func selectnbrecv(elem *any, hchan <-chan any) bool
|
func selectnbrecv(elem *any, hchan <-chan any) bool
|
||||||
|
func selectnbrecv2(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)
|
||||||
func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
|
func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
|
||||||
|
func selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) (selected bool)
|
||||||
func selectdefault(sel *byte) (selected bool)
|
func selectdefault(sel *byte) (selected bool)
|
||||||
func selectgo(sel *byte)
|
func selectgo(sel *byte)
|
||||||
func block()
|
func block()
|
||||||
|
@ -58,6 +58,18 @@ typecheckselect(Node *sel)
|
|||||||
n->op = OSELRECV;
|
n->op = OSELRECV;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OAS2RECV:
|
||||||
|
// convert x, ok = <-c into OSELRECV(x, <-c) with ntest=ok
|
||||||
|
if(n->right->op != ORECV) {
|
||||||
|
yyerror("select assignment must have receive on right hand side");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n->op = OSELRECV2;
|
||||||
|
n->left = n->list->n;
|
||||||
|
n->ntest = n->list->next->n;
|
||||||
|
n->right = n->rlist->n;
|
||||||
|
break;
|
||||||
|
|
||||||
case ORECV:
|
case ORECV:
|
||||||
// convert <-c into OSELRECV(N, <-c)
|
// convert <-c into OSELRECV(N, <-c)
|
||||||
n = nod(OSELRECV, N, n);
|
n = nod(OSELRECV, N, n);
|
||||||
@ -122,6 +134,18 @@ walkselect(Node *sel)
|
|||||||
typecheck(&n, Etop);
|
typecheck(&n, Etop);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OSELRECV2:
|
||||||
|
r = n->right;
|
||||||
|
ch = cheapexpr(r->left, &l);
|
||||||
|
r->left = ch;
|
||||||
|
|
||||||
|
a = nod(OAS2, N, N);
|
||||||
|
a->list = n->list;
|
||||||
|
a->rlist = n->rlist;
|
||||||
|
n = a;
|
||||||
|
typecheck(&n, Etop);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ch == nil { block() }; n;
|
// if ch == nil { block() }; n;
|
||||||
@ -146,6 +170,7 @@ walkselect(Node *sel)
|
|||||||
continue;
|
continue;
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
case OSELRECV:
|
case OSELRECV:
|
||||||
|
case OSELRECV2:
|
||||||
ch = n->right->left;
|
ch = n->right->left;
|
||||||
|
|
||||||
// If we can use the address of the target without
|
// If we can use the address of the target without
|
||||||
@ -154,6 +179,28 @@ walkselect(Node *sel)
|
|||||||
// Also introduce a temporary for := variables that escape,
|
// Also introduce a temporary for := variables that escape,
|
||||||
// so that we can delay the heap allocation until the case
|
// so that we can delay the heap allocation until the case
|
||||||
// is selected.
|
// is selected.
|
||||||
|
if(n->op == OSELRECV2) {
|
||||||
|
if(n->ntest == N || isblank(n->ntest))
|
||||||
|
n->ntest = nodnil();
|
||||||
|
else if(n->ntest->op == ONAME &&
|
||||||
|
(!n->colas || (n->ntest->class&PHEAP) == 0) &&
|
||||||
|
convertop(types[TBOOL], n->ntest->type, nil) == OCONVNOP) {
|
||||||
|
n->ntest = nod(OADDR, n->ntest, N);
|
||||||
|
n->ntest->etype = 1; // pointer does not escape
|
||||||
|
typecheck(&n->ntest, Erv);
|
||||||
|
} else {
|
||||||
|
tmp = nod(OXXX, N, N);
|
||||||
|
tempname(tmp, types[TBOOL]);
|
||||||
|
a = nod(OADDR, tmp, N);
|
||||||
|
a->etype = 1; // pointer does not escape
|
||||||
|
typecheck(&a, Erv);
|
||||||
|
r = nod(OAS, n->ntest, tmp);
|
||||||
|
typecheck(&r, Etop);
|
||||||
|
cas->nbody = concat(list1(r), cas->nbody);
|
||||||
|
n->ntest = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(n->left == N || isblank(n->left))
|
if(n->left == N || isblank(n->left))
|
||||||
n->left = nodnil();
|
n->left = nodnil();
|
||||||
else if(n->left->op == ONAME &&
|
else if(n->left->op == ONAME &&
|
||||||
@ -171,10 +218,12 @@ walkselect(Node *sel)
|
|||||||
r = nod(OAS, n->left, tmp);
|
r = nod(OAS, n->left, tmp);
|
||||||
typecheck(&r, Etop);
|
typecheck(&r, Etop);
|
||||||
cas->nbody = concat(list1(r), cas->nbody);
|
cas->nbody = concat(list1(r), cas->nbody);
|
||||||
cas->nbody = concat(n->ninit, cas->nbody);
|
|
||||||
n->ninit = nil;
|
|
||||||
n->left = a;
|
n->left = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cas->nbody = concat(n->ninit, cas->nbody);
|
||||||
|
n->ninit = nil;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +261,16 @@ walkselect(Node *sel)
|
|||||||
mkcall1(chanfn("selectnbrecv", 2, ch->type),
|
mkcall1(chanfn("selectnbrecv", 2, ch->type),
|
||||||
types[TBOOL], &r->ninit, n->left, ch));
|
types[TBOOL], &r->ninit, n->left, ch));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OSELRECV2:
|
||||||
|
// if c != nil && selectnbrecv2(&v, c) { body } else { default body }
|
||||||
|
r = nod(OIF, N, N);
|
||||||
|
r->ninit = cas->ninit;
|
||||||
|
ch = cheapexpr(n->right->left, &r->ninit);
|
||||||
|
r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()),
|
||||||
|
mkcall1(chanfn("selectnbrecv2", 2, ch->type),
|
||||||
|
types[TBOOL], &r->ninit, n->left, n->ntest, ch));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
typecheck(&r->ntest, Erv);
|
typecheck(&r->ntest, Erv);
|
||||||
r->nbody = cas->nbody;
|
r->nbody = cas->nbody;
|
||||||
@ -254,11 +313,18 @@ walkselect(Node *sel)
|
|||||||
r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
|
r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
|
||||||
&init, var, n->left, n->right);
|
&init, var, n->left, n->right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSELRECV:
|
case OSELRECV:
|
||||||
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
||||||
r->ntest = mkcall1(chanfn("selectrecv", 2, n->right->left->type), types[TBOOL],
|
r->ntest = mkcall1(chanfn("selectrecv", 2, n->right->left->type), types[TBOOL],
|
||||||
&init, var, n->right->left, n->left);
|
&init, var, n->right->left, n->left);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OSELRECV2:
|
||||||
|
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
|
||||||
|
r->ntest = mkcall1(chanfn("selectrecv2", 2, n->right->left->type), types[TBOOL],
|
||||||
|
&init, var, n->right->left, n->left, n->ntest);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r->nbody = concat(r->nbody, cas->nbody);
|
r->nbody = concat(r->nbody, cas->nbody);
|
||||||
|
@ -94,7 +94,7 @@ init1(Node *n, NodeList **out)
|
|||||||
case OAS2FUNC:
|
case OAS2FUNC:
|
||||||
case OAS2MAPR:
|
case OAS2MAPR:
|
||||||
case OAS2DOTTYPE:
|
case OAS2DOTTYPE:
|
||||||
case OAS2RECVCLOSED:
|
case OAS2RECV:
|
||||||
if(n->defn->initorder)
|
if(n->defn->initorder)
|
||||||
break;
|
break;
|
||||||
n->defn->initorder = 1;
|
n->defn->initorder = 1;
|
||||||
|
@ -834,7 +834,6 @@ goopnames[] =
|
|||||||
[OCALL] = "function call",
|
[OCALL] = "function call",
|
||||||
[OCAP] = "cap",
|
[OCAP] = "cap",
|
||||||
[OCASE] = "case",
|
[OCASE] = "case",
|
||||||
[OCLOSED] = "closed",
|
|
||||||
[OCLOSE] = "close",
|
[OCLOSE] = "close",
|
||||||
[OCOMPLEX] = "complex",
|
[OCOMPLEX] = "complex",
|
||||||
[OCOM] = "^",
|
[OCOM] = "^",
|
||||||
@ -1669,6 +1668,9 @@ isselect(Node *n)
|
|||||||
if(s == n->sym)
|
if(s == n->sym)
|
||||||
return 1;
|
return 1;
|
||||||
s = pkglookup("selectrecv", runtimepkg);
|
s = pkglookup("selectrecv", runtimepkg);
|
||||||
|
if(s == n->sym)
|
||||||
|
return 1;
|
||||||
|
s = pkglookup("selectrecv2", runtimepkg);
|
||||||
if(s == n->sym)
|
if(s == n->sym)
|
||||||
return 1;
|
return 1;
|
||||||
s = pkglookup("selectdefault", runtimepkg);
|
s = pkglookup("selectdefault", runtimepkg);
|
||||||
|
@ -921,7 +921,6 @@ reswitch:
|
|||||||
n->type = t;
|
n->type = t;
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCLOSED:
|
|
||||||
case OCLOSE:
|
case OCLOSE:
|
||||||
if(onearg(n, "%#O", n->op) < 0)
|
if(onearg(n, "%#O", n->op) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -934,10 +933,6 @@ reswitch:
|
|||||||
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
|
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if(n->op == OCLOSED) {
|
|
||||||
n->type = types[TBOOL];
|
|
||||||
ok |= Erv;
|
|
||||||
} else
|
|
||||||
ok |= Etop;
|
ok |= Etop;
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
@ -2377,8 +2372,9 @@ typecheckas2(Node *n)
|
|||||||
n->op = OAS2MAPR;
|
n->op = OAS2MAPR;
|
||||||
goto common;
|
goto common;
|
||||||
case ORECV:
|
case ORECV:
|
||||||
yyerror("cannot use multiple-value assignment for non-blocking receive; use select");
|
n->op = OAS2RECV;
|
||||||
goto out;
|
n->right = n->rlist->n;
|
||||||
|
goto common;
|
||||||
case ODOTTYPE:
|
case ODOTTYPE:
|
||||||
n->op = OAS2DOTTYPE;
|
n->op = OAS2DOTTYPE;
|
||||||
r->op = ODOTTYPE2;
|
r->op = ODOTTYPE2;
|
||||||
|
@ -403,12 +403,11 @@ walkstmt(Node **np)
|
|||||||
case OAS:
|
case OAS:
|
||||||
case OAS2:
|
case OAS2:
|
||||||
case OAS2DOTTYPE:
|
case OAS2DOTTYPE:
|
||||||
case OAS2RECVCLOSED:
|
case OAS2RECV:
|
||||||
case OAS2FUNC:
|
case OAS2FUNC:
|
||||||
case OAS2MAPW:
|
case OAS2MAPW:
|
||||||
case OAS2MAPR:
|
case OAS2MAPR:
|
||||||
case OCLOSE:
|
case OCLOSE:
|
||||||
case OCLOSED:
|
|
||||||
case OCOPY:
|
case OCOPY:
|
||||||
case OCALLMETH:
|
case OCALLMETH:
|
||||||
case OCALLINTER:
|
case OCALLINTER:
|
||||||
@ -822,14 +821,13 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
n = liststmt(concat(concat(list1(r), ll), lpost));
|
n = liststmt(concat(concat(list1(r), ll), lpost));
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OAS2RECVCLOSED:
|
case OAS2RECV:
|
||||||
// a = <-c; b = closed(c) but atomic
|
|
||||||
*init = concat(*init, n->ninit);
|
*init = concat(*init, n->ninit);
|
||||||
n->ninit = nil;
|
n->ninit = nil;
|
||||||
r = n->rlist->n;
|
r = n->rlist->n;
|
||||||
walkexprlistsafe(n->list, init);
|
walkexprlistsafe(n->list, init);
|
||||||
walkexpr(&r->left, init);
|
walkexpr(&r->left, init);
|
||||||
fn = chanfn("chanrecv3", 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, r->left);
|
||||||
n->rlist->n = r;
|
n->rlist->n = r;
|
||||||
n->op = OAS2FUNC;
|
n->op = OAS2FUNC;
|
||||||
@ -1309,13 +1307,6 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
n = mkcall1(fn, T, init, n->left);
|
n = mkcall1(fn, T, init, n->left);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCLOSED:
|
|
||||||
// cannot use chanfn - closechan takes any, not chan any
|
|
||||||
fn = syslook("closedchan", 1);
|
|
||||||
argtype(fn, n->left->type);
|
|
||||||
n = mkcall1(fn, n->type, init, n->left);
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
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->type),
|
||||||
|
@ -7,12 +7,6 @@
|
|||||||
|
|
||||||
static int32 debug = 0;
|
static int32 debug = 0;
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
Wclosed = 0x0001, // writer has closed
|
|
||||||
Rclosed = 0x0002, // reader has seen close
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct Link Link;
|
typedef struct Link Link;
|
||||||
typedef struct WaitQ WaitQ;
|
typedef struct WaitQ WaitQ;
|
||||||
typedef struct SudoG SudoG;
|
typedef struct SudoG SudoG;
|
||||||
@ -40,7 +34,7 @@ struct Hchan
|
|||||||
uint32 qcount; // total data in the q
|
uint32 qcount; // total data in the q
|
||||||
uint32 dataqsiz; // size of the circular q
|
uint32 dataqsiz; // size of the circular q
|
||||||
uint16 elemsize;
|
uint16 elemsize;
|
||||||
uint16 closed; // Wclosed Rclosed errorcount
|
bool closed;
|
||||||
uint8 elemalign;
|
uint8 elemalign;
|
||||||
Alg* elemalg; // interface for element type
|
Alg* elemalg; // interface for element type
|
||||||
Link* senddataq; // pointer for sender
|
Link* senddataq; // pointer for sender
|
||||||
@ -57,15 +51,26 @@ struct Link
|
|||||||
byte elem[8]; // asynch queue data element (+ more)
|
byte elem[8]; // asynch queue data element (+ more)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
// Scase.kind
|
||||||
|
CaseRecv,
|
||||||
|
CaseSend,
|
||||||
|
CaseDefault,
|
||||||
|
};
|
||||||
|
|
||||||
struct Scase
|
struct Scase
|
||||||
{
|
{
|
||||||
Hchan* chan; // chan
|
Hchan* chan; // chan
|
||||||
byte* pc; // return pc
|
byte* pc; // return pc
|
||||||
uint16 send; // 0-recv 1-send 2-default
|
uint16 kind;
|
||||||
uint16 so; // vararg of selected bool
|
uint16 so; // vararg of selected bool
|
||||||
union {
|
union {
|
||||||
byte elem[8]; // element (send)
|
byte elem[2*sizeof(void*)]; // element (send)
|
||||||
|
struct {
|
||||||
byte* elemp; // pointer to element (recv)
|
byte* elemp; // pointer to element (recv)
|
||||||
|
bool* receivedp; // pointer to received bool (recv2)
|
||||||
|
} recv;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,7 +188,7 @@ runtime·chansend(Hchan *c, byte *ep, bool *pres)
|
|||||||
|
|
||||||
runtime·lock(c);
|
runtime·lock(c);
|
||||||
loop:
|
loop:
|
||||||
if(c->closed & Wclosed)
|
if(c->closed)
|
||||||
goto closed;
|
goto closed;
|
||||||
|
|
||||||
if(c->dataqsiz > 0)
|
if(c->dataqsiz > 0)
|
||||||
@ -228,7 +233,7 @@ loop:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
asynch:
|
asynch:
|
||||||
if(c->closed & Wclosed)
|
if(c->closed)
|
||||||
goto closed;
|
goto closed;
|
||||||
|
|
||||||
if(c->qcount >= c->dataqsiz) {
|
if(c->qcount >= c->dataqsiz) {
|
||||||
@ -269,7 +274,7 @@ closed:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
runtime·chanrecv(Hchan* c, byte *ep, bool *pres, bool *closed)
|
runtime·chanrecv(Hchan* c, byte *ep, bool *selected, bool *received)
|
||||||
{
|
{
|
||||||
SudoG *sg;
|
SudoG *sg;
|
||||||
G *gp;
|
G *gp;
|
||||||
@ -284,14 +289,12 @@ runtime·chanrecv(Hchan* c, byte *ep, bool *pres, bool *closed)
|
|||||||
runtime·printf("chanrecv: chan=%p\n", c);
|
runtime·printf("chanrecv: chan=%p\n", c);
|
||||||
|
|
||||||
runtime·lock(c);
|
runtime·lock(c);
|
||||||
if(closed != nil)
|
|
||||||
*closed = false;
|
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
if(c->dataqsiz > 0)
|
if(c->dataqsiz > 0)
|
||||||
goto asynch;
|
goto asynch;
|
||||||
|
|
||||||
if(c->closed & Wclosed)
|
if(c->closed)
|
||||||
goto closed;
|
goto closed;
|
||||||
|
|
||||||
sg = dequeue(&c->sendq, c);
|
sg = dequeue(&c->sendq, c);
|
||||||
@ -305,14 +308,16 @@ loop:
|
|||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
runtime·ready(gp);
|
runtime·ready(gp);
|
||||||
|
|
||||||
if(pres != nil)
|
if(selected != nil)
|
||||||
*pres = true;
|
*selected = true;
|
||||||
|
if(received != nil)
|
||||||
|
*received = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pres != nil) {
|
if(selected != nil) {
|
||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
*pres = false;
|
*selected = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,18 +336,20 @@ loop:
|
|||||||
if(ep != nil)
|
if(ep != nil)
|
||||||
c->elemalg->copy(c->elemsize, ep, sg->elem);
|
c->elemalg->copy(c->elemsize, ep, sg->elem);
|
||||||
c->elemalg->copy(c->elemsize, sg->elem, nil);
|
c->elemalg->copy(c->elemsize, sg->elem, nil);
|
||||||
|
if(received != nil)
|
||||||
|
*received = true;
|
||||||
freesg(c, sg);
|
freesg(c, sg);
|
||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
asynch:
|
asynch:
|
||||||
if(c->qcount <= 0) {
|
if(c->qcount <= 0) {
|
||||||
if(c->closed & Wclosed)
|
if(c->closed)
|
||||||
goto closed;
|
goto closed;
|
||||||
|
|
||||||
if(pres != nil) {
|
if(selected != nil) {
|
||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
*pres = false;
|
*selected = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sg = allocsg(c);
|
sg = allocsg(c);
|
||||||
@ -365,24 +372,22 @@ asynch:
|
|||||||
freesg(c, sg);
|
freesg(c, sg);
|
||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
runtime·ready(gp);
|
runtime·ready(gp);
|
||||||
if(pres != nil)
|
} else
|
||||||
*pres = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
if(pres != nil)
|
|
||||||
*pres = true;
|
if(selected != nil)
|
||||||
|
*selected = true;
|
||||||
|
if(received != nil)
|
||||||
|
*received = true;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
closed:
|
closed:
|
||||||
if(closed != nil)
|
|
||||||
*closed = true;
|
|
||||||
if(ep != nil)
|
if(ep != nil)
|
||||||
c->elemalg->copy(c->elemsize, ep, nil);
|
c->elemalg->copy(c->elemsize, ep, nil);
|
||||||
c->closed |= Rclosed;
|
if(selected != nil)
|
||||||
if(pres != nil)
|
*selected = true;
|
||||||
*pres = true;
|
if(received != nil)
|
||||||
|
*received = false;
|
||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,16 +421,16 @@ runtime·chanrecv1(Hchan* c, ...)
|
|||||||
runtime·chanrecv(c, ae, nil, nil);
|
runtime·chanrecv(c, ae, nil, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
// chanrecv3(hchan *chan any) (elem any, closed bool);
|
// chanrecv2(hchan *chan any) (elem any, received bool);
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·chanrecv3(Hchan* c, ...)
|
runtime·chanrecv2(Hchan* c, ...)
|
||||||
{
|
{
|
||||||
int32 o;
|
int32 o;
|
||||||
byte *ae, *ac;
|
byte *ae, *ac;
|
||||||
|
|
||||||
if(c == nil)
|
if(c == nil)
|
||||||
runtime·panicstring("range over nil channel");
|
runtime·panicstring("receive from nil channel");
|
||||||
|
|
||||||
o = runtime·rnd(sizeof(c), Structrnd);
|
o = runtime·rnd(sizeof(c), Structrnd);
|
||||||
ae = (byte*)&c + o;
|
ae = (byte*)&c + o;
|
||||||
@ -490,9 +495,35 @@ runtime·selectnbsend(Hchan *c, ...)
|
|||||||
//
|
//
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·selectnbrecv(byte *v, Hchan *c, bool ok)
|
runtime·selectnbrecv(byte *v, Hchan *c, bool selected)
|
||||||
{
|
{
|
||||||
runtime·chanrecv(c, v, &ok, nil);
|
runtime·chanrecv(c, v, &selected, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
|
||||||
|
//
|
||||||
|
// compiler implements
|
||||||
|
//
|
||||||
|
// select {
|
||||||
|
// case v = <-c:
|
||||||
|
// ... foo
|
||||||
|
// default:
|
||||||
|
// ... bar
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// as
|
||||||
|
//
|
||||||
|
// if c != nil && selectnbrecv(&v, c) {
|
||||||
|
// ... foo
|
||||||
|
// } else {
|
||||||
|
// ... bar
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
#pragma textflag 7
|
||||||
|
void
|
||||||
|
runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected)
|
||||||
|
{
|
||||||
|
runtime·chanrecv(c, v, &selected, received);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newselect(int32, Select**);
|
static void newselect(int32, Select**);
|
||||||
@ -556,22 +587,22 @@ runtime·selectsend(Select *sel, Hchan *c, ...)
|
|||||||
eo = runtime·rnd(sizeof(sel), sizeof(c));
|
eo = runtime·rnd(sizeof(sel), sizeof(c));
|
||||||
eo = runtime·rnd(eo+sizeof(c), c->elemsize);
|
eo = runtime·rnd(eo+sizeof(c), c->elemsize);
|
||||||
cas->so = runtime·rnd(eo+c->elemsize, Structrnd);
|
cas->so = runtime·rnd(eo+c->elemsize, Structrnd);
|
||||||
cas->send = 1;
|
cas->kind = CaseSend;
|
||||||
|
|
||||||
ae = (byte*)&sel + eo;
|
ae = (byte*)&sel + eo;
|
||||||
c->elemalg->copy(c->elemsize, cas->u.elem, ae);
|
c->elemalg->copy(c->elemsize, cas->u.elem, ae);
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
runtime·printf("selectsend s=%p pc=%p chan=%p so=%d send=%d\n",
|
runtime·printf("selectsend s=%p pc=%p chan=%p so=%d\n",
|
||||||
sel, cas->pc, cas->chan, cas->so, cas->send);
|
sel, cas->pc, cas->chan, cas->so);
|
||||||
}
|
}
|
||||||
|
|
||||||
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·selectrecv(Select *sel, Hchan *c, ...)
|
runtime·selectrecv(Select *sel, Hchan *c, void *elem, bool selected)
|
||||||
{
|
{
|
||||||
int32 i, eo;
|
int32 i;
|
||||||
Scase *cas;
|
Scase *cas;
|
||||||
|
|
||||||
// nil cases do not compete
|
// nil cases do not compete
|
||||||
@ -587,30 +618,60 @@ runtime·selectrecv(Select *sel, Hchan *c, ...)
|
|||||||
cas->pc = runtime·getcallerpc(&sel);
|
cas->pc = runtime·getcallerpc(&sel);
|
||||||
cas->chan = c;
|
cas->chan = c;
|
||||||
|
|
||||||
eo = runtime·rnd(sizeof(sel), sizeof(c));
|
cas->so = (byte*)&selected - (byte*)&sel;
|
||||||
eo = runtime·rnd(eo+sizeof(c), sizeof(byte*));
|
cas->kind = CaseRecv;
|
||||||
cas->so = runtime·rnd(eo+sizeof(byte*), Structrnd);
|
cas->u.recv.elemp = elem;
|
||||||
cas->send = 0;
|
cas->u.recv.receivedp = nil;
|
||||||
cas->u.elemp = *(byte**)((byte*)&sel + eo);
|
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
runtime·printf("selectrecv s=%p pc=%p chan=%p so=%d send=%d\n",
|
runtime·printf("selectrecv s=%p pc=%p chan=%p so=%d\n",
|
||||||
sel, cas->pc, cas->chan, cas->so, cas->send);
|
sel, cas->pc, cas->chan, cas->so);
|
||||||
|
}
|
||||||
|
|
||||||
|
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
|
||||||
|
#pragma textflag 7
|
||||||
|
void
|
||||||
|
runtime·selectrecv2(Select *sel, Hchan *c, void *elem, bool *received, bool selected)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
Scase *cas;
|
||||||
|
|
||||||
|
// nil cases do not compete
|
||||||
|
if(c == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
i = sel->ncase;
|
||||||
|
if(i >= sel->tcase)
|
||||||
|
runtime·throw("selectrecv: too many cases");
|
||||||
|
sel->ncase = i+1;
|
||||||
|
cas = runtime·mal(sizeof *cas);
|
||||||
|
sel->scase[i] = cas;
|
||||||
|
cas->pc = runtime·getcallerpc(&sel);
|
||||||
|
cas->chan = c;
|
||||||
|
|
||||||
|
cas->so = (byte*)&selected - (byte*)&sel;
|
||||||
|
cas->kind = CaseRecv;
|
||||||
|
cas->u.recv.elemp = elem;
|
||||||
|
cas->u.recv.receivedp = received;
|
||||||
|
|
||||||
|
if(debug)
|
||||||
|
runtime·printf("selectrecv2 s=%p pc=%p chan=%p so=%d elem=%p recv=%p\n",
|
||||||
|
sel, cas->pc, cas->chan, cas->so, cas->u.recv.elemp, cas->u.recv.receivedp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void selectdefault(Select*, void*);
|
static void selectdefault(Select*, void*, int32);
|
||||||
|
|
||||||
// selectdefault(sel *byte) (selected bool);
|
// selectdefault(sel *byte) (selected bool);
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·selectdefault(Select *sel, ...)
|
runtime·selectdefault(Select *sel, bool selected)
|
||||||
{
|
{
|
||||||
selectdefault(sel, runtime·getcallerpc(&sel));
|
selectdefault(sel, runtime·getcallerpc(&sel), (byte*)&selected - (byte*)&sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
selectdefault(Select *sel, void *callerpc)
|
selectdefault(Select *sel, void *callerpc, int32 so)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
Scase *cas;
|
Scase *cas;
|
||||||
@ -624,13 +685,12 @@ selectdefault(Select *sel, void *callerpc)
|
|||||||
cas->pc = callerpc;
|
cas->pc = callerpc;
|
||||||
cas->chan = nil;
|
cas->chan = nil;
|
||||||
|
|
||||||
cas->so = runtime·rnd(sizeof(sel), Structrnd);
|
cas->so = so;
|
||||||
cas->send = 2;
|
cas->kind = CaseDefault;
|
||||||
cas->u.elemp = nil;
|
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
runtime·printf("selectdefault s=%p pc=%p so=%d send=%d\n",
|
runtime·printf("selectdefault s=%p pc=%p so=%d\n",
|
||||||
sel, cas->pc, cas->so, cas->send);
|
sel, cas->pc, cas->so);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -747,8 +807,8 @@ loop:
|
|||||||
cas = sel->scase[o];
|
cas = sel->scase[o];
|
||||||
c = cas->chan;
|
c = cas->chan;
|
||||||
|
|
||||||
switch(cas->send) {
|
switch(cas->kind) {
|
||||||
case 0: // recv
|
case CaseRecv:
|
||||||
if(c->dataqsiz > 0) {
|
if(c->dataqsiz > 0) {
|
||||||
if(c->qcount > 0)
|
if(c->qcount > 0)
|
||||||
goto asyncrecv;
|
goto asyncrecv;
|
||||||
@ -757,12 +817,12 @@ loop:
|
|||||||
if(sg != nil)
|
if(sg != nil)
|
||||||
goto syncrecv;
|
goto syncrecv;
|
||||||
}
|
}
|
||||||
if(c->closed & Wclosed)
|
if(c->closed)
|
||||||
goto rclose;
|
goto rclose;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // send
|
case CaseSend:
|
||||||
if(c->closed & Wclosed)
|
if(c->closed)
|
||||||
goto sclose;
|
goto sclose;
|
||||||
if(c->dataqsiz > 0) {
|
if(c->dataqsiz > 0) {
|
||||||
if(c->qcount < c->dataqsiz)
|
if(c->qcount < c->dataqsiz)
|
||||||
@ -774,7 +834,7 @@ loop:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // default
|
case CaseDefault:
|
||||||
dfl = cas;
|
dfl = cas;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -794,12 +854,12 @@ loop:
|
|||||||
sg = allocsg(c);
|
sg = allocsg(c);
|
||||||
sg->offset = o;
|
sg->offset = o;
|
||||||
|
|
||||||
switch(cas->send) {
|
switch(cas->kind) {
|
||||||
case 0: // recv
|
case CaseRecv:
|
||||||
enqueue(&c->recvq, sg);
|
enqueue(&c->recvq, sg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // send
|
case CaseSend:
|
||||||
if(c->dataqsiz == 0)
|
if(c->dataqsiz == 0)
|
||||||
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
|
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
|
||||||
enqueue(&c->sendq, sg);
|
enqueue(&c->sendq, sg);
|
||||||
@ -821,7 +881,7 @@ loop:
|
|||||||
if(sg == nil || i != sg->offset) {
|
if(sg == nil || i != sg->offset) {
|
||||||
cas = sel->scase[i];
|
cas = sel->scase[i];
|
||||||
c = cas->chan;
|
c = cas->chan;
|
||||||
if(cas->send)
|
if(cas->kind == CaseSend)
|
||||||
dequeueg(&c->sendq, c);
|
dequeueg(&c->sendq, c);
|
||||||
else
|
else
|
||||||
dequeueg(&c->recvq, c);
|
dequeueg(&c->recvq, c);
|
||||||
@ -841,12 +901,14 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
runtime·printf("wait-return: sel=%p c=%p cas=%p send=%d o=%d\n",
|
runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d o=%d\n",
|
||||||
sel, c, cas, cas->send, o);
|
sel, c, cas, cas->kind, o);
|
||||||
|
|
||||||
if(!cas->send) {
|
if(cas->kind == CaseRecv) {
|
||||||
if(cas->u.elemp != nil)
|
if(cas->u.recv.receivedp != nil)
|
||||||
c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
|
*cas->u.recv.receivedp = true;
|
||||||
|
if(cas->u.recv.elemp != nil)
|
||||||
|
c->elemalg->copy(c->elemsize, cas->u.recv.elemp, sg->elem);
|
||||||
c->elemalg->copy(c->elemsize, sg->elem, nil);
|
c->elemalg->copy(c->elemsize, sg->elem, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -855,8 +917,10 @@ loop:
|
|||||||
|
|
||||||
asyncrecv:
|
asyncrecv:
|
||||||
// can receive from buffer
|
// can receive from buffer
|
||||||
if(cas->u.elemp != nil)
|
if(cas->u.recv.receivedp != nil)
|
||||||
c->elemalg->copy(c->elemsize, cas->u.elemp, c->recvdataq->elem);
|
*cas->u.recv.receivedp = true;
|
||||||
|
if(cas->u.recv.elemp != nil)
|
||||||
|
c->elemalg->copy(c->elemsize, cas->u.recv.elemp, c->recvdataq->elem);
|
||||||
c->elemalg->copy(c->elemsize, c->recvdataq->elem, nil);
|
c->elemalg->copy(c->elemsize, c->recvdataq->elem, nil);
|
||||||
c->recvdataq = c->recvdataq->link;
|
c->recvdataq = c->recvdataq->link;
|
||||||
c->qcount--;
|
c->qcount--;
|
||||||
@ -886,8 +950,10 @@ syncrecv:
|
|||||||
// can receive from sleeping sender (sg)
|
// can receive from sleeping sender (sg)
|
||||||
if(debug)
|
if(debug)
|
||||||
runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
|
runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
|
||||||
if(cas->u.elemp != nil)
|
if(cas->u.recv.receivedp != nil)
|
||||||
c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
|
*cas->u.recv.receivedp = true;
|
||||||
|
if(cas->u.recv.elemp != nil)
|
||||||
|
c->elemalg->copy(c->elemsize, cas->u.recv.elemp, sg->elem);
|
||||||
c->elemalg->copy(c->elemsize, sg->elem, nil);
|
c->elemalg->copy(c->elemsize, sg->elem, nil);
|
||||||
gp = sg->g;
|
gp = sg->g;
|
||||||
gp->param = sg;
|
gp->param = sg;
|
||||||
@ -896,16 +962,17 @@ syncrecv:
|
|||||||
|
|
||||||
rclose:
|
rclose:
|
||||||
// read at end of closed channel
|
// read at end of closed channel
|
||||||
if(cas->u.elemp != nil)
|
if(cas->u.recv.receivedp != nil)
|
||||||
c->elemalg->copy(c->elemsize, cas->u.elemp, nil);
|
*cas->u.recv.receivedp = false;
|
||||||
c->closed |= Rclosed;
|
if(cas->u.recv.elemp != nil)
|
||||||
|
c->elemalg->copy(c->elemsize, cas->u.recv.elemp, nil);
|
||||||
goto retc;
|
goto retc;
|
||||||
|
|
||||||
syncsend:
|
syncsend:
|
||||||
// can send to sleeping receiver (sg)
|
// can send to sleeping receiver (sg)
|
||||||
if(debug)
|
if(debug)
|
||||||
runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
|
runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
|
||||||
if(c->closed & Wclosed)
|
if(c->closed)
|
||||||
goto sclose;
|
goto sclose;
|
||||||
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
|
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
|
||||||
gp = sg->g;
|
gp = sg->g;
|
||||||
@ -916,7 +983,6 @@ retc:
|
|||||||
selunlock(sel);
|
selunlock(sel);
|
||||||
|
|
||||||
// return to pc corresponding to chosen case
|
// return to pc corresponding to chosen case
|
||||||
|
|
||||||
pc = cas->pc;
|
pc = cas->pc;
|
||||||
as = (byte*)selp + cas->so;
|
as = (byte*)selp + cas->so;
|
||||||
freesel(sel);
|
freesel(sel);
|
||||||
@ -941,12 +1007,12 @@ runtime·closechan(Hchan *c)
|
|||||||
runtime·gosched();
|
runtime·gosched();
|
||||||
|
|
||||||
runtime·lock(c);
|
runtime·lock(c);
|
||||||
if(c->closed & Wclosed) {
|
if(c->closed) {
|
||||||
runtime·unlock(c);
|
runtime·unlock(c);
|
||||||
runtime·panicstring("close of closed channel");
|
runtime·panicstring("close of closed channel");
|
||||||
}
|
}
|
||||||
|
|
||||||
c->closed |= Wclosed;
|
c->closed = true;
|
||||||
|
|
||||||
// release all readers
|
// release all readers
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@ -979,12 +1045,6 @@ runtime·chanclose(Hchan *c)
|
|||||||
runtime·closechan(c);
|
runtime·closechan(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
runtime·chanclosed(Hchan *c)
|
|
||||||
{
|
|
||||||
return (c->closed & Rclosed) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
runtime·chanlen(Hchan *c)
|
runtime·chanlen(Hchan *c)
|
||||||
{
|
{
|
||||||
@ -997,15 +1057,6 @@ runtime·chancap(Hchan *c)
|
|||||||
return c->dataqsiz;
|
return c->dataqsiz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// closedchan(sel *byte) bool;
|
|
||||||
void
|
|
||||||
runtime·closedchan(Hchan *c, bool closed)
|
|
||||||
{
|
|
||||||
closed = runtime·chanclosed(c);
|
|
||||||
FLUSH(&closed);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SudoG*
|
static SudoG*
|
||||||
dequeue(WaitQ *q, Hchan *c)
|
dequeue(WaitQ *q, Hchan *c)
|
||||||
{
|
{
|
||||||
|
@ -70,22 +70,18 @@ func makechan(typ *byte, size uint32) (ch *byte) {
|
|||||||
ch = (byte*)runtime·makechan_c(t->elem, size);
|
ch = (byte*)runtime·makechan_c(t->elem, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
func chansend(ch *byte, val *byte, pres *bool) {
|
func chansend(ch *byte, val *byte, selected *bool) {
|
||||||
runtime·chansend((Hchan*)ch, val, pres);
|
runtime·chansend((Hchan*)ch, val, selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
func chanrecv(ch *byte, val *byte, pres *bool) {
|
func chanrecv(ch *byte, val *byte, selected *bool, received *bool) {
|
||||||
runtime·chanrecv((Hchan*)ch, val, pres, nil);
|
runtime·chanrecv((Hchan*)ch, val, selected, received);
|
||||||
}
|
}
|
||||||
|
|
||||||
func chanclose(ch *byte) {
|
func chanclose(ch *byte) {
|
||||||
runtime·chanclose((Hchan*)ch);
|
runtime·chanclose((Hchan*)ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
func chanclosed(ch *byte) (r bool) {
|
|
||||||
r = runtime·chanclosed((Hchan*)ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
func chanlen(ch *byte) (r int32) {
|
func chanlen(ch *byte) (r int32) {
|
||||||
r = runtime·chanlen((Hchan*)ch);
|
r = runtime·chanlen((Hchan*)ch);
|
||||||
}
|
}
|
||||||
|
@ -585,7 +585,6 @@ Hchan* runtime·makechan_c(Type*, int64);
|
|||||||
void runtime·chansend(Hchan*, void*, bool*);
|
void runtime·chansend(Hchan*, void*, bool*);
|
||||||
void runtime·chanrecv(Hchan*, void*, bool*, bool*);
|
void runtime·chanrecv(Hchan*, void*, bool*, bool*);
|
||||||
void runtime·chanclose(Hchan*);
|
void runtime·chanclose(Hchan*);
|
||||||
bool runtime·chanclosed(Hchan*);
|
|
||||||
int32 runtime·chanlen(Hchan*);
|
int32 runtime·chanlen(Hchan*);
|
||||||
int32 runtime·chancap(Hchan*);
|
int32 runtime·chancap(Hchan*);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user