startup classage expr211 { main(String[] args) { create X(); } } classage X { X() { ::t(create Y(), create Y()); } singleton connector A { import void t0() export void t1() { print("OK from export t1"); print("now passive call for t1 from inside t1 of A"); t0(); print("passive call ends"); print("now the value of per-connection state connf is " + connf); connf = 3; print("now the value of per-connection state connf is " + connf); } state int connf = 0; } void t(Y y1, Y y2) { A x1, x2; print("[1]"); // if the following line is not commented out, runtime exception // will be thrown because the connector is currently not satisfied. // A::t0(); print("[2]"); // if the following line is not commented out, runtime exception // will be thrown because the connector is currently not satisfied. // NOTE: for singleton pluggers, invocation to an export is // allowed even when the plugger is not plugged with any plugin, // this is because plugger is always stateless. This is not true // for connectors. Connectors might have per-connection states: // had we allowed invocation to a connector not currently // connected to any other objectage, we would end up have // uninialized per-connection states if the export touches it. // A::t1(); print("[4]"); // the following line should have no effect, since currently // A is not connected forall(h::A) {print("now inside forall before connect:"); h->t0();} print("[5]"); //connect happens here x1 = connect y1 with A >> B; print("[6]"); // now the t0 defined by B should be invoked, pure import case A::t0(); print("[7]"); // the following line has the same effect as above for the // singleton case x1->t0(); print("[10]"); // now the t1 defined by A should be invoked, pure export case A::t1(); print("[11]"); // the following line has the same effect as above for the // singleton case x1->t1(); print("[12]"); // the following line should now invoke t0 defined by A, since // currently A is connected to y1 forall(h::A) {print("now inside forall after connect:"); h->t0(); } print("[13]"); // if the following line is not commented out, runtime exception // will be thrown because the connector is singleton and can not be // connected with more than one objectage. // x2 = connect y2 with A >> B; print("[14]"); //disconnect disconnect x1; print("[15]"); // the following line should have no effect, since currently // A is not connected. forall(h::A) {print("now inside forall after disconnect:"); h->t0();} print("[16]"); // if the following line is not commented out, runtime exception // will be thrown because the connector is currently not satisfied. // A::t0(); // A::t1(); print("[18]"); // if the following lines are not commented out, runtime exception // will be thrown because x1 is currently stale. // x1->t0(); // x1->t1(); print("[19]"); //cascaded connect/disconnect disconnect (connect y1 with A >> B); return; } } classage Y { singleton connector B { export void t0() { print("OK from export t0 of B"); return; } export void t1() { print("OK from export t1 of B"); return; } } }