/** * Tests the situation in an enabling sequence where the alt enables guard A, * then while it is enabling guard B (A < B), guard A fires. Even though the guard * has already been dealt, the alt should notice, and not block at the end of its enable */ static TestResult test2() { BEGIN_TEST() SetUp setup; BufferedOne2OneChannel<unsigned> c(FIFOBuffer<unsigned>::Factory(1)); WaitingGuard* guard1; WaitingGuard* guard2; Barrier barrier; ScopedBarrierEnd barrierEnd(barrier.enrolledEnd()); TestAlt* talt = new TestAlt(barrier.enrolledEnd()); Guard* result = NULL; talt->guards.resize(4); talt->guards[0] = new TestGuard(&result); talt->guards[1] = guard1 = new WaitingGuard(&result,true); talt->guards[2] = guard2 = new WaitingGuard(&result,true); talt->guards[3] = new TestGuard(&result); EvaluateFunction< unsigned, TestAlt >* _alter = new EvaluateFunction< unsigned, TestAlt >(*talt,c.writer()); ProcessPtr alter(getProcessPtr(_alter)); ScopedForking forking; set<EventList> expA_0,expA_1; //expA_0 is blank (the version where they don't block on the barrier) expA_1 += tuple_list_of (alter,NullProcessPtr,NullProcessPtr) //They block on the barrier ; set<EventList> actA; { RecordEvents _(&actA); forking.fork(_alter); guard1->waitForWait(); talt->guards[0]->fire(); guard1->free(); guard2->waitForWait(); guard2->free(); } barrierEnd.sync(); ASSERTEQ1OF2(expA_0,expA_1,actA,"Events not as expected in part A",__LINE__); assertAllGuardsEmpty(talt); barrierEnd.sync(); unsigned sel; c.reader() >> sel; ASSERTEQ(0,sel,"Alternative did not select the correct guard",__LINE__); ASSERTEQ(talt->guards[0],result,"Alternative did not activate the correct guard",__LINE__); END_TEST("Alt test 2"); }
/** * Tests the situation in which the alt disable sequence is running, and has reached guard B, * where some guard C (B < C) had fired after all guards had been enabled. Guard A (A < B < C) is then fired. */ static TestResult test4() { BEGIN_TEST() SetUp setup; BufferedOne2OneChannel<unsigned> c(FIFOBuffer<unsigned>::Factory(1)); WaitingGuard* guard1; Barrier barrier; ScopedBarrierEnd barrierEnd(barrier.enrolledEnd()); TestAlt* talt = new TestAlt(barrier.enrolledEnd()); Guard* result = NULL; talt->guards.resize(4); talt->guards[0] = new TestGuard(&result); talt->guards[1] = guard1 = new WaitingGuard(&result,false); talt->guards[2] = new TestGuard(&result); talt->guards[3] = new TestGuard(&result); EvaluateFunction< unsigned, TestAlt >* _alter = new EvaluateFunction< unsigned, TestAlt >(*talt,c.writer()); ProcessPtr alter(getProcessPtr(_alter)); CPPCSP_Yield(); { ScopedForking forking; set<EventList> expA_0,expA_1; expA_0 += tuple_list_of (alter,NullProcessPtr,NullProcessPtr) //They block on the barrier ; expA_0 += tuple_list_of (us,alter,alter) //We free them ; //In 0, they don't block on the barrier expA_1 += tuple_list_of (alter,NullProcessPtr,NullProcessPtr) //They block on the alt (alter,NullProcessPtr,NullProcessPtr) //They block on the barrier ; expA_1 += tuple_list_of (us,alter,alter) //We free them ; set<EventList> actA; { RecordEvents _(&actA); //Guard is already fired: forking.fork(_alter); while (AtomicGet(&(alter->alting)) != ___ALTING_WAITING) { Thread_Yield(); } talt->guards[2]->fire(); guard1->waitForWait(); talt->guards[0]->fire(); guard1->free(); } barrierEnd.sync(); ASSERTEQ1OF2(expA_0,expA_1,actA,"Events not as expected in part A",__LINE__); assertAllGuardsEmpty(talt); barrierEnd.sync(); unsigned sel; c.reader() >> sel; ASSERTEQ(0,sel,"Alternative did not select the correct guard",__LINE__); ASSERTEQ(talt->guards[0],result,"Alternative did not activate the correct guard",__LINE__); } END_TEST("Alt test 4"); }
/** * Tests alts blocking when no guards are ready, and then awaking *once* when multiple guards fire */ static TestResult test1() { BEGIN_TEST() SetUp setup; ScopedForking forking; BufferedOne2OneChannel<unsigned> c(FIFOBuffer<unsigned>::Factory(1)); Barrier barrier; ScopedBarrierEnd barrierEnd(barrier.enrolledEnd()); TestAlt* talt = new TestAlt(barrier.enrolledEnd()); Guard* result = NULL; talt->guards.resize(4); for (unsigned i = 0;i < 4;i++) { talt->guards[i] = new TestGuard(&result); } EvaluateFunction< unsigned, TestAlt >* _alter = new EvaluateFunction< unsigned, TestAlt >(*talt,c.writer()); ProcessPtr alter(getProcessPtr(_alter)); EventList expA = tuple_list_of (us,alter,alter) //We start them up (us,us,us) (us,NullProcessPtr,NullProcessPtr) //we yield (alter,NullProcessPtr,NullProcessPtr) //they must block, waiting for the guards ; EventList actA; { RecordEvents _(&actA); forking.forkInThisThread(_alter); CPPCSP_Yield(); } ASSERTEQ(expA,actA,"Events not as expected in part A",__LINE__); ASSERTEQ(alter,talt->guards[0]->process,"Data (0.process) not as expected",__LINE__); ASSERTEQ(alter,talt->guards[1]->process,"Data (1.process) not as expected",__LINE__); ASSERTEQ(alter,talt->guards[2]->process,"Data (2.process) not as expected",__LINE__); ASSERTEQ(alter,talt->guards[3]->process,"Data (3.process) not as expected",__LINE__); ASSERTEQ(false,talt->guards[0]->fired,"Data (0.fired) not as expected",__LINE__); ASSERTEQ(false,talt->guards[1]->fired,"Data (1.fired) not as expected",__LINE__); ASSERTEQ(false,talt->guards[2]->fired,"Data (2.fired) not as expected",__LINE__); ASSERTEQ(false,talt->guards[3]->fired,"Data (3.fired) not as expected",__LINE__); EventList expB = tuple_list_of (us,alter,alter) //We fire guard[3]. //Firing guards[2] and guards[1] have no effect on the run-queue (us,us,us) (us,NullProcessPtr,NullProcessPtr) //we yield (alter,NullProcessPtr,NullProcessPtr) //they block on the barrier ; EventList actB; { RecordEvents _(&actB); talt->guards[3]->fire(); talt->guards[2]->fire(); talt->guards[1]->fire(); CPPCSP_Yield(); } ASSERTEQ(expB,actB,"Events not as expected in part B",__LINE__); assertAllGuardsEmpty(talt); barrierEnd.sync(); barrierEnd.sync(); unsigned sel; c.reader() >> sel; ASSERTEQ(1,sel,"Alternative did not select the correct guard",__LINE__); ASSERTEQ(talt->guards[1],result,"Alternative did not activate the correct guard",__LINE__); delete talt; END_TEST("Alt Test 1"); }