"func \"\".mapiter2 (hiter *any) (key any, val any)\n"
"func \"\".makechan (elem *uint8, hint int64) chan 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 \"\".closechan (hchan any)\n"
"func \"\".closedchan (hchan any) bool\n"
"func \"\".selectnbsend (hchan chan<- any, elem 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 \"\".selectsend (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 \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
OARRAY,
OARRAYBYTESTR, OARRAYRUNESTR,
OSTRARRAYBYTE, OSTRARRAYRUNE,
- OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECVCLOSED, OAS2MAPR, OAS2DOTTYPE, OASOP,
+ OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE, OASOP,
OBAD,
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
OCAP,
OCLOSE,
- OCLOSED,
OCLOSURE,
OCMPIFACE, OCMPSTR,
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
ORECV,
ORUNESTR,
OSELRECV,
+ OSELRECV2,
OIOTA,
OREAL, OIMAG, OCOMPLEX,
}
break;
}
-| LCASE expr '=' expr ':'
+| LCASE expr_or_type_list '=' expr ':'
{
+ Node *n;
+
// will be converted to OCASE
// right will point to next case
// done in casebody()
poptodcl();
$$ = 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);
+ }
+ $$->list = list1(n);
}
-| LCASE name LCOLAS expr ':'
+| LCASE expr_or_type_list LCOLAS expr ':'
{
// will be converted to OCASE
// right will point to next case
// done in casebody()
poptodcl();
$$ = nod(OXCASE, N, N);
- $$->list = list1(colas(list1($2), list1($4)));
+ $$->list = list1(colas($2, list1($4)));
}
| LDEFAULT ':'
{
"append", LNAME, Txxx, OAPPEND,
"cap", LNAME, Txxx, OCAP,
"close", LNAME, Txxx, OCLOSE,
- "closed", LNAME, Txxx, OCLOSED,
"complex", LNAME, Txxx, OCOMPLEX,
"copy", LNAME, Txxx, OCOPY,
"imag", LNAME, Txxx, OIMAG,
case OARRAYBYTESTR:
case OCAP:
case OCLOSE:
- case OCLOSED:
case OCOPY:
case OLEN:
case OMAKE:
case OAPPEND:
case OCAP:
case OCLOSE:
- case OCLOSED:
case OLEN:
case OCOPY:
case OMAKE:
hb = nod(OXXX, N, N);
tempname(hb, types[TBOOL]);
- n->ntest = nod(ONOT, hb, N);
- a = nod(OAS2RECVCLOSED, N, N);
+ n->ntest = hb;
+ a = nod(OAS2RECV, N, N);
a->typecheck = 1;
a->list = list(list1(hv1), hb);
a->rlist = list1(nod(ORECV, ha, N));
// *byte is really *runtime.Type
func makechan(elem *byte, hint int64) (hchan chan 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 closechan(hchan any)
func closedchan(hchan any) bool
func selectnbsend(hchan chan<- any, elem 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 selectsend(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 selectgo(sel *byte)
func block()
n->op = OSELRECV;
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:
// convert <-c into OSELRECV(N, <-c)
n = nod(OSELRECV, N, n);
typecheck(&n, Etop);
}
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;
continue;
switch(n->op) {
case OSELRECV:
+ case OSELRECV2:
ch = n->right->left;
// If we can use the address of the target without
// Also introduce a temporary for := variables that escape,
// so that we can delay the heap allocation until the case
// 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))
n->left = nodnil();
else if(n->left->op == ONAME &&
r = nod(OAS, n->left, tmp);
typecheck(&r, Etop);
cas->nbody = concat(list1(r), cas->nbody);
- cas->nbody = concat(n->ninit, cas->nbody);
- n->ninit = nil;
n->left = a;
}
+
+ cas->nbody = concat(n->ninit, cas->nbody);
+ n->ninit = nil;
+ break;
}
}
mkcall1(chanfn("selectnbrecv", 2, ch->type),
types[TBOOL], &r->ninit, n->left, ch));
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);
r->nbody = cas->nbody;
r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
&init, var, n->left, n->right);
break;
+
case OSELRECV:
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
r->ntest = mkcall1(chanfn("selectrecv", 2, n->right->left->type), types[TBOOL],
&init, var, n->right->left, n->left);
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);
case OAS2FUNC:
case OAS2MAPR:
case OAS2DOTTYPE:
- case OAS2RECVCLOSED:
+ case OAS2RECV:
if(n->defn->initorder)
break;
n->defn->initorder = 1;
[OCALL] = "function call",
[OCAP] = "cap",
[OCASE] = "case",
- [OCLOSED] = "closed",
[OCLOSE] = "close",
[OCOMPLEX] = "complex",
[OCOM] = "^",
if(s == n->sym)
return 1;
s = pkglookup("selectrecv", runtimepkg);
+ if(s == n->sym)
+ return 1;
+ s = pkglookup("selectrecv2", runtimepkg);
if(s == n->sym)
return 1;
s = pkglookup("selectdefault", runtimepkg);
n->type = t;
goto ret;
- case OCLOSED:
case OCLOSE:
if(onearg(n, "%#O", n->op) < 0)
goto error;
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
goto error;
}
- if(n->op == OCLOSED) {
- n->type = types[TBOOL];
- ok |= Erv;
- } else
- ok |= Etop;
+ ok |= Etop;
goto ret;
case OAPPEND:
n->op = OAS2MAPR;
goto common;
case ORECV:
- yyerror("cannot use multiple-value assignment for non-blocking receive; use select");
- goto out;
+ n->op = OAS2RECV;
+ n->right = n->rlist->n;
+ goto common;
case ODOTTYPE:
n->op = OAS2DOTTYPE;
r->op = ODOTTYPE2;
case OAS:
case OAS2:
case OAS2DOTTYPE:
- case OAS2RECVCLOSED:
+ case OAS2RECV:
case OAS2FUNC:
case OAS2MAPW:
case OAS2MAPR:
case OCLOSE:
- case OCLOSED:
case OCOPY:
case OCALLMETH:
case OCALLINTER:
n = liststmt(concat(concat(list1(r), ll), lpost));
goto ret;
- case OAS2RECVCLOSED:
- // a = <-c; b = closed(c) but atomic
+ case OAS2RECV:
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
walkexprlistsafe(n->list, 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);
n->rlist->n = r;
n->op = OAS2FUNC;
n = mkcall1(fn, T, init, n->left);
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:
n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
typename(n->type->type),
static int32 debug = 0;
-enum
-{
- Wclosed = 0x0001, // writer has closed
- Rclosed = 0x0002, // reader has seen close
-};
-
typedef struct Link Link;
typedef struct WaitQ WaitQ;
typedef struct SudoG SudoG;
uint32 qcount; // total data in the q
uint32 dataqsiz; // size of the circular q
uint16 elemsize;
- uint16 closed; // Wclosed Rclosed errorcount
+ bool closed;
uint8 elemalign;
Alg* elemalg; // interface for element type
Link* senddataq; // pointer for sender
byte elem[8]; // asynch queue data element (+ more)
};
+enum
+{
+ // Scase.kind
+ CaseRecv,
+ CaseSend,
+ CaseDefault,
+};
+
struct Scase
{
Hchan* chan; // chan
byte* pc; // return pc
- uint16 send; // 0-recv 1-send 2-default
+ uint16 kind;
uint16 so; // vararg of selected bool
union {
- byte elem[8]; // element (send)
- byte* elemp; // pointer to element (recv)
+ byte elem[2*sizeof(void*)]; // element (send)
+ struct {
+ byte* elemp; // pointer to element (recv)
+ bool* receivedp; // pointer to received bool (recv2)
+ } recv;
} u;
};
runtime·lock(c);
loop:
- if(c->closed & Wclosed)
+ if(c->closed)
goto closed;
if(c->dataqsiz > 0)
return;
asynch:
- if(c->closed & Wclosed)
+ if(c->closed)
goto closed;
if(c->qcount >= c->dataqsiz) {
}
void
-runtime·chanrecv(Hchan* c, byte *ep, bool *pres, bool *closed)
+runtime·chanrecv(Hchan* c, byte *ep, bool *selected, bool *received)
{
SudoG *sg;
G *gp;
runtime·printf("chanrecv: chan=%p\n", c);
runtime·lock(c);
- if(closed != nil)
- *closed = false;
loop:
if(c->dataqsiz > 0)
goto asynch;
- if(c->closed & Wclosed)
+ if(c->closed)
goto closed;
sg = dequeue(&c->sendq, c);
runtime·unlock(c);
runtime·ready(gp);
- if(pres != nil)
- *pres = true;
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = true;
return;
}
- if(pres != nil) {
+ if(selected != nil) {
runtime·unlock(c);
- *pres = false;
+ *selected = false;
return;
}
if(ep != nil)
c->elemalg->copy(c->elemsize, ep, sg->elem);
c->elemalg->copy(c->elemsize, sg->elem, nil);
+ if(received != nil)
+ *received = true;
freesg(c, sg);
runtime·unlock(c);
return;
asynch:
if(c->qcount <= 0) {
- if(c->closed & Wclosed)
+ if(c->closed)
goto closed;
- if(pres != nil) {
+ if(selected != nil) {
runtime·unlock(c);
- *pres = false;
+ *selected = false;
return;
}
sg = allocsg(c);
freesg(c, sg);
runtime·unlock(c);
runtime·ready(gp);
- if(pres != nil)
- *pres = true;
- return;
- }
+ } else
+ runtime·unlock(c);
- runtime·unlock(c);
- if(pres != nil)
- *pres = true;
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = true;
return;
closed:
- if(closed != nil)
- *closed = true;
if(ep != nil)
c->elemalg->copy(c->elemsize, ep, nil);
- c->closed |= Rclosed;
- if(pres != nil)
- *pres = true;
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = false;
runtime·unlock(c);
}
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
void
-runtime·chanrecv3(Hchan* c, ...)
+runtime·chanrecv2(Hchan* c, ...)
{
int32 o;
byte *ae, *ac;
if(c == nil)
- runtime·panicstring("range over nil channel");
+ runtime·panicstring("receive from nil channel");
o = runtime·rnd(sizeof(c), Structrnd);
ae = (byte*)&c + o;
//
#pragma textflag 7
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**);
eo = runtime·rnd(sizeof(sel), sizeof(c));
eo = runtime·rnd(eo+sizeof(c), c->elemsize);
cas->so = runtime·rnd(eo+c->elemsize, Structrnd);
- cas->send = 1;
+ cas->kind = CaseSend;
ae = (byte*)&sel + eo;
c->elemalg->copy(c->elemsize, cas->u.elem, ae);
if(debug)
- runtime·printf("selectsend s=%p pc=%p chan=%p so=%d send=%d\n",
- sel, cas->pc, cas->chan, cas->so, cas->send);
+ runtime·printf("selectsend s=%p pc=%p chan=%p so=%d\n",
+ sel, cas->pc, cas->chan, cas->so);
}
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
#pragma textflag 7
void
-runtime·selectrecv(Select *sel, Hchan *c, ...)
+runtime·selectrecv(Select *sel, Hchan *c, void *elem, bool selected)
{
- int32 i, eo;
+ int32 i;
Scase *cas;
// nil cases do not compete
cas->pc = runtime·getcallerpc(&sel);
cas->chan = c;
- eo = runtime·rnd(sizeof(sel), sizeof(c));
- eo = runtime·rnd(eo+sizeof(c), sizeof(byte*));
- cas->so = runtime·rnd(eo+sizeof(byte*), Structrnd);
- cas->send = 0;
- cas->u.elemp = *(byte**)((byte*)&sel + eo);
+ cas->so = (byte*)&selected - (byte*)&sel;
+ cas->kind = CaseRecv;
+ cas->u.recv.elemp = elem;
+ cas->u.recv.receivedp = nil;
+
+ if(debug)
+ runtime·printf("selectrecv s=%p pc=%p chan=%p so=%d\n",
+ 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("selectrecv s=%p pc=%p chan=%p so=%d send=%d\n",
- sel, cas->pc, cas->chan, cas->so, cas->send);
+ 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);
#pragma textflag 7
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
-selectdefault(Select *sel, void *callerpc)
+selectdefault(Select *sel, void *callerpc, int32 so)
{
int32 i;
Scase *cas;
cas->pc = callerpc;
cas->chan = nil;
- cas->so = runtime·rnd(sizeof(sel), Structrnd);
- cas->send = 2;
- cas->u.elemp = nil;
+ cas->so = so;
+ cas->kind = CaseDefault;
if(debug)
- runtime·printf("selectdefault s=%p pc=%p so=%d send=%d\n",
- sel, cas->pc, cas->so, cas->send);
+ runtime·printf("selectdefault s=%p pc=%p so=%d\n",
+ sel, cas->pc, cas->so);
}
static void
cas = sel->scase[o];
c = cas->chan;
- switch(cas->send) {
- case 0: // recv
+ switch(cas->kind) {
+ case CaseRecv:
if(c->dataqsiz > 0) {
if(c->qcount > 0)
goto asyncrecv;
if(sg != nil)
goto syncrecv;
}
- if(c->closed & Wclosed)
+ if(c->closed)
goto rclose;
break;
- case 1: // send
- if(c->closed & Wclosed)
+ case CaseSend:
+ if(c->closed)
goto sclose;
if(c->dataqsiz > 0) {
if(c->qcount < c->dataqsiz)
}
break;
- case 2: // default
+ case CaseDefault:
dfl = cas;
break;
}
sg = allocsg(c);
sg->offset = o;
- switch(cas->send) {
- case 0: // recv
+ switch(cas->kind) {
+ case CaseRecv:
enqueue(&c->recvq, sg);
break;
- case 1: // send
+ case CaseSend:
if(c->dataqsiz == 0)
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
enqueue(&c->sendq, sg);
if(sg == nil || i != sg->offset) {
cas = sel->scase[i];
c = cas->chan;
- if(cas->send)
+ if(cas->kind == CaseSend)
dequeueg(&c->sendq, c);
else
dequeueg(&c->recvq, c);
}
if(debug)
- runtime·printf("wait-return: sel=%p c=%p cas=%p send=%d o=%d\n",
- sel, c, cas, cas->send, o);
-
- if(!cas->send) {
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
+ runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d o=%d\n",
+ sel, c, cas, cas->kind, o);
+
+ if(cas->kind == CaseRecv) {
+ if(cas->u.recv.receivedp != nil)
+ *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);
}
asyncrecv:
// can receive from buffer
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, c->recvdataq->elem);
+ if(cas->u.recv.receivedp != nil)
+ *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->recvdataq = c->recvdataq->link;
c->qcount--;
// can receive from sleeping sender (sg)
if(debug)
runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
+ if(cas->u.recv.receivedp != nil)
+ *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);
gp = sg->g;
gp->param = sg;
rclose:
// read at end of closed channel
- if(cas->u.elemp != nil)
- c->elemalg->copy(c->elemsize, cas->u.elemp, nil);
- c->closed |= Rclosed;
+ if(cas->u.recv.receivedp != nil)
+ *cas->u.recv.receivedp = false;
+ if(cas->u.recv.elemp != nil)
+ c->elemalg->copy(c->elemsize, cas->u.recv.elemp, nil);
goto retc;
syncsend:
// can send to sleeping receiver (sg)
if(debug)
runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
- if(c->closed & Wclosed)
+ if(c->closed)
goto sclose;
c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem);
gp = sg->g;
selunlock(sel);
// return to pc corresponding to chosen case
-
pc = cas->pc;
as = (byte*)selp + cas->so;
freesel(sel);
runtime·gosched();
runtime·lock(c);
- if(c->closed & Wclosed) {
+ if(c->closed) {
runtime·unlock(c);
runtime·panicstring("close of closed channel");
}
- c->closed |= Wclosed;
+ c->closed = true;
// release all readers
for(;;) {
runtime·closechan(c);
}
-bool
-runtime·chanclosed(Hchan *c)
-{
- return (c->closed & Rclosed) != 0;
-}
-
int32
runtime·chanlen(Hchan *c)
{
return c->dataqsiz;
}
-
-// closedchan(sel *byte) bool;
-void
-runtime·closedchan(Hchan *c, bool closed)
-{
- closed = runtime·chanclosed(c);
- FLUSH(&closed);
-}
-
static SudoG*
dequeue(WaitQ *q, Hchan *c)
{
ch = (byte*)runtime·makechan_c(t->elem, size);
}
-func chansend(ch *byte, val *byte, pres *bool) {
- runtime·chansend((Hchan*)ch, val, pres);
+func chansend(ch *byte, val *byte, selected *bool) {
+ runtime·chansend((Hchan*)ch, val, selected);
}
-func chanrecv(ch *byte, val *byte, pres *bool) {
- runtime·chanrecv((Hchan*)ch, val, pres, nil);
+func chanrecv(ch *byte, val *byte, selected *bool, received *bool) {
+ runtime·chanrecv((Hchan*)ch, val, selected, received);
}
func chanclose(ch *byte) {
runtime·chanclose((Hchan*)ch);
}
-func chanclosed(ch *byte) (r bool) {
- r = runtime·chanclosed((Hchan*)ch);
-}
-
func chanlen(ch *byte) (r int32) {
r = runtime·chanlen((Hchan*)ch);
}
void runtime·chansend(Hchan*, void*, bool*);
void runtime·chanrecv(Hchan*, void*, bool*, bool*);
void runtime·chanclose(Hchan*);
-bool runtime·chanclosed(Hchan*);
int32 runtime·chanlen(Hchan*);
int32 runtime·chancap(Hchan*);