runtime not finished.
R=r
OCL=26217
CL=26217
test -f y.tab.c && touch y.tab.c
builtin.c: sys.go unsafe.go mkbuiltin1.c mkbuiltin
- mkbuiltin >builtin.c || \
+ ./mkbuiltin >builtin.c || \
(echo 'mkbuiltin failed; using bootstrap copy of builtin.c'; cp builtin.c.boot builtin.c)
clean:
"func sys.chanrecv3 (hchan chan any, elem *any) (pres bool)\n"
"func sys.chansend1 (hchan chan any, elem any)\n"
"func sys.chansend2 (hchan chan any, elem any) (pres bool)\n"
+ "func sys.closechan (hchan chan any)\n"
+ "func sys.closedchan (hchan chan any) (? bool)\n"
"func sys.newselect (size int) (sel *uint8)\n"
"func sys.selectsend (sel *uint8, hchan chan any, elem any) (selected bool)\n"
"func sys.selectrecv (sel *uint8, hchan chan any, elem *any) (selected bool)\n"
OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL,
OGOTO, OPROC, OMAKE, ONEW, OEMPTY, OSELECT,
OLEN, OCAP, OPANIC, OPANICN, OPRINT, OPRINTN, OTYPEOF,
+ OCLOSE, OCLOSED,
OOROR,
OANDAND,
%token <val> LLITERAL
%token <lint> LASOP
%token <sym> LNAME LBASETYPE LATYPE LPACK LACONST
-%token <sym> LPACKAGE LIMPORT LDEFER
+%token <sym> LPACKAGE LIMPORT LDEFER LCLOSE LCLOSED
%token <sym> LMAP LCHAN LINTERFACE LFUNC LSTRUCT
%token <sym> LCOLAS LFALL LRETURN LDDD
%token <sym> LLEN LCAP LPANIC LPANICN LPRINT LPRINTN
{
$$ = nod(OLEN, $3, N);
}
+| LCLOSE '(' expr ')'
+ {
+ $$ = nod(OCLOSE, $3, N);
+ }
+| LCLOSED '(' expr ')'
+ {
+ $$ = nod(OCLOSED, $3, N);
+ }
| LCAP '(' expr ')'
{
$$ = nod(OCAP, $3, N);
sym3:
LLEN
| LCAP
+| LCLOSE
+| LCLOSED
| LPANIC
| LPANICN
| LPRINT
"any", LBASETYPE, TANY,
"sys", LPACK, Txxx,
-/* keywords */
"break", LBREAK, Txxx,
"case", LCASE, Txxx,
"chan", LCHAN, Txxx,
"type", LTYPE, Txxx,
"var", LVAR, Txxx,
+ "close", LCLOSE, Txxx,
+ "closed", LCLOSED, Txxx,
+
"notwithstanding", LIGNORE, Txxx,
"thetruthofthematter", LIGNORE, Txxx,
"despiteallobjections", LIGNORE, Txxx,
ken | r | rsc)
if ! cmp _builtin.c builtin.c.boot
then
- p4 open builtin.c.boot
+ PATH=$PATH:/usr/local/bin
+ p4 open builtin.c.boot >/dev/null
cp _builtin.c builtin.c.boot
fi
esac
[OLABEL] = "LABEL",
[OLE] = "LE",
[OLEN] = "LEN",
+ [OCLOSE] = "CLOSE",
+ [OCLOSED] = "CLOSED",
[OCAP] = "CAP",
[OLIST] = "LIST",
[OLITERAL] = "LITERAL",
func chanrecv3(hchan chan any, elem *any) (pres bool);
func chansend1(hchan chan any, elem any);
func chansend2(hchan chan any, elem any) (pres bool);
+func closechan(hchan chan any);
+func closedchan(hchan chan any) bool;
func newselect(size int) (sel *byte);
func selectsend(sel *byte, hchan chan any, elem any) (selected bool);
case OASOP:
case OAS:
+ case OCLOSE:
+ case OCLOSED:
case OCALLMETH:
case OCALLINTER:
case OCALL:
}
goto ret;
+ case OCLOSE:
+ if(top != Etop)
+ goto nottop;
+ walktype(n->left, Erv); // chan
+ indir(n, chanop(n, top));
+ goto ret;
+
+ case OCLOSED:
+ if(top == Elv)
+ goto nottop;
+ walktype(n->left, Erv); // chan
+ indir(n, chanop(n, top));
+ goto ret;
+
case OSEND:
if(top == Elv)
goto nottop;
default:
fatal("chanop: unknown op %O", n->op);
+ case OCLOSE:
+ // closechan(hchan *chan any);
+ t = fixchan(n->left->type);
+ if(t == T)
+ break;
+
+ a = n->left; // chan
+ r = a;
+
+ on = syslook("closechan", 1);
+ argtype(on, t->type); // any-1
+
+ r = nod(OCALL, on, r);
+ walktype(r, top);
+ r->type = n->type;
+ break;
+
+ case OCLOSED:
+ // closedchan(hchan *chan any) bool;
+ t = fixchan(n->left->type);
+ if(t == T)
+ break;
+
+ a = n->left; // chan
+ r = a;
+
+ on = syslook("closedchan", 1);
+ argtype(on, t->type); // any-1
+
+ r = nod(OCALL, on, r);
+ walktype(r, top);
+ n->type = r->type;
+ break;
+
case OMAKE:
cl = listcount(n->left);
if(cl > 1)
static int32 debug = 0;
static Lock chanlock;
+enum
+{
+ Wclosed = 0x0001,
+ Rclosed = 0xfffe,
+ Rincr = 0x0002,
+ Rmax = 0x8000,
+};
+
typedef struct Hchan Hchan;
typedef struct Link Link;
typedef struct WaitQ WaitQ;
struct Hchan
{
- uint32 elemsize;
+ uint16 elemsize;
+ uint16 closed; // Wclosed closed() hash been called
+ // Rclosed read-count after closed()
uint32 dataqsiz; // size of the circular q
uint32 qcount; // total data in the q
Alg* elemalg; // interface for element type
}
}
-
// selectgo(sel *byte);
void
sys·selectgo(Select *sel)
*as = true;
}
+// closechan(sel *byte);
+void
+sys·closechan(Hchan *c)
+{
+ if(c == nil)
+ throw("closechan: channel not allocated");
+
+ // if wclosed already set
+ // work has been done - just return
+ if(c->closed & Wclosed)
+ return;
+
+ // set wclosed
+ c->closed |= Wclosed;
+}
+
+// closedchan(sel *byte) bool;
+void
+sys·closedchan(Hchan *c, bool closed)
+{
+ if(c == nil)
+ throw("closedchan: channel not allocated");
+
+ closed = 0;
+
+ // test rclosed
+ if(c->closed & Rclosed) {
+ // see if rclosed has been set a lot
+ if(c->closed & Rmax)
+ throw("closedchan: ignored");
+ c->closed += Rincr;
+ closed = 1;
+ }
+ FLUSH(&closed);
+}
+
static SudoG*
dequeue(WaitQ *q, Hchan *c)
{