diff options
author | Russ Cox <rsc@golang.org> | 2009-03-23 18:50:35 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-03-23 18:50:35 -0700 |
commit | 362494a9f69b24358c6a50e962648929ac3118fd (patch) | |
tree | 419e2f2fb716f5389fefb545bfb8be86a8c23522 /src/runtime | |
parent | d071d1916a77a05f69136db0694aef3eafc9b230 (diff) | |
download | golang-362494a9f69b24358c6a50e962648929ac3118fd.tar.gz |
add test for close/closed, fix a few implementation bugs.
R=ken
OCL=26664
CL=26664
Diffstat (limited to 'src/runtime')
-rw-r--r-- | src/runtime/chan.c | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/src/runtime/chan.c b/src/runtime/chan.c index c5e53410e..59ac78d79 100644 --- a/src/runtime/chan.c +++ b/src/runtime/chan.c @@ -176,13 +176,13 @@ sendchan(Hchan *c, byte *ep, bool *pres) } lock(&chanlock); +loop: + if(c->closed & Wclosed) + goto closed; if(c->dataqsiz > 0) goto asynch; - if(c->closed & Wclosed) - goto closed; - sg = dequeue(&c->recvq, c); if(sg != nil) { if(ep != nil) @@ -215,6 +215,8 @@ sendchan(Hchan *c, byte *ep, bool *pres) lock(&chanlock); sg = g->param; + if(sg == nil) + goto loop; freesg(c, sg); unlock(&chanlock); if(pres != nil) @@ -260,7 +262,7 @@ asynch: closed: incerr(c); if(pres != nil) - *pres = false; + *pres = true; unlock(&chanlock); } @@ -277,6 +279,7 @@ chanrecv(Hchan* c, byte *ep, bool* pres) } lock(&chanlock); +loop: if(c->dataqsiz > 0) goto asynch; @@ -312,11 +315,8 @@ chanrecv(Hchan* c, byte *ep, bool* pres) lock(&chanlock); sg = g->param; - - if(c->closed & Wclosed) { - freesg(c, sg); - goto closed; - } + if(sg == nil) + goto loop; c->elemalg->copy(c->elemsize, ep, sg->elem); freesg(c, sg); @@ -368,7 +368,7 @@ closed: c->closed |= Rclosed; incerr(c); if(pres != nil) - *pres = false; + *pres = true; unlock(&chanlock); } @@ -651,32 +651,32 @@ loop: c = cas->chan; if(c->dataqsiz > 0) { if(cas->send) { + if(c->closed & Wclosed) + goto sclose; if(c->qcount < c->dataqsiz) goto asyns; - if(c->closed & Wclosed) - goto gots; goto next1; } if(c->qcount > 0) goto asynr; if(c->closed & Wclosed) - goto gotr; + goto rclose; goto next1; } if(cas->send) { + if(c->closed & Wclosed) + goto sclose; sg = dequeue(&c->recvq, c); if(sg != nil) goto gots; - if(c->closed & Wclosed) - goto gots; goto next1; } sg = dequeue(&c->sendq, c); if(sg != nil) goto gotr; if(c->closed & Wclosed) - goto gotr; + goto rclose; next1: o += p; @@ -823,13 +823,6 @@ gotr: sys·printint(o); prints("\n"); } - if(c->closed & Wclosed) { - if(cas->u.elemp != nil) - c->elemalg->copy(c->elemsize, cas->u.elemp, nil); - c->closed |= Rclosed; - incerr(c); - goto retc; - } if(cas->u.elemp != nil) c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem); gp = sg->g; @@ -837,6 +830,13 @@ gotr: ready(gp); goto retc; +rclose: + if(cas->u.elemp != nil) + c->elemalg->copy(c->elemsize, cas->u.elemp, nil); + c->closed |= Rclosed; + incerr(c); + goto retc; + gots: // send path to wakeup the receiver (sg) if(debug) { @@ -848,14 +848,17 @@ gots: sys·printint(o); prints("\n"); } - if(c->closed & Wclosed) { - incerr(c); - goto retc; - } + if(c->closed & Wclosed) + goto sclose; c->elemalg->copy(c->elemsize, sg->elem, cas->u.elem); gp = sg->g; gp->param = sg; ready(gp); + goto retc; + +sclose: + incerr(c); + goto retc; retc: if(sel->ncase >= 1 && sel->ncase < nelem(selfree)) { @@ -909,7 +912,6 @@ sys·closechan(Hchan *c) void sys·closedchan(Hchan *c, bool closed) { - // test Rclosed closed = 0; if(c->closed & Rclosed) |