diff options
author | Ambroz Bizjak <ambrop7@gmail.com> | 2014-12-07 02:30:12 +0300 |
---|---|---|
committer | Ambroz Bizjak <ambrop7@gmail.com> | 2014-12-07 02:30:12 +0300 |
commit | f20999da6205ff8d89b3c25c34c91f3a158b53bc (patch) | |
tree | 13eb4aca88c1e41f081f215f91a1b7ea86a8bce0 | |
parent | ca4547bf41d0d38cf8baf34f358e0b6756fcebc7 (diff) |
ncd: Reverse the immediate effect logic of backtrack_point::rgo().
Turns out we want the backtrack triggering effects to have priority. Consider the following test case.
process main {
backtrack_point() pointA;
println("A");
sleep("1");
If ("true") {
backtrack_point() pointB;
println("B");
pointA->rgo();
pointB->go();
};
}
The result of this would originally have been "A B B B B...". The reason is that the If process would be caught in an infinite loop, and the main process would never get a chance to backtrack past the If statement. With this change, the result is "A B A B...", since the rgo() deinitialization immediately causes backtracking in main.
This is actually a nice example about a design bug regarding the subtle ways in which a process call (If, in this case) is not equivalent to embedding the statements in place. Without the If, there would not be an infinite loop in any case.
-rw-r--r-- | ncd/modules/backtrack.c | 15 | ||||
-rw-r--r-- | ncd/tests/backtracking.ncd | 6 |
2 files changed, 14 insertions, 7 deletions
diff --git a/ncd/modules/backtrack.c b/ncd/modules/backtrack.c index 468315c..2e0f704 100644 --- a/ncd/modules/backtrack.c +++ b/ncd/modules/backtrack.c @@ -40,8 +40,8 @@ * itself goes up immedietely, but side effects of triggering backtracking have * priority. * The rgo() method triggers backtracking when it deinitializes. In this case, - * the immediate effects of rgo() deinitialization happen before the immediate - * effects of triggering backtracking in the backtrack_point(). + * the immediate effects of triggering backtracking in the backtrack_point() have + * priority over the immediate effects of rgo() deinitialization completion. */ #include <ncd/module_common.h> @@ -121,11 +121,11 @@ static void rgo_func_die (void *vo) { struct rgo_instance *o = vo; - // toggle backtrack point + // deref backtrack_point + NCDModuleInst *backtrack_point_inst = NULL; NCDObject rgo_obj; if (NCDObjRef_Deref(&o->bp_ref, &rgo_obj)) { - NCDModuleInst *backtrack_point_inst = NCDObject_MethodUser(&rgo_obj); - NCDModuleInst_Backend_DownUp(backtrack_point_inst); + backtrack_point_inst = NCDObject_MethodUser(&rgo_obj); } // free object reference @@ -133,6 +133,11 @@ static void rgo_func_die (void *vo) // die NCDModuleInst_Backend_Dead(o->i); + + // toggle backtrack_point + if (backtrack_point_inst) { + NCDModuleInst_Backend_DownUp(backtrack_point_inst); + } } static struct NCDModule modules[] = { diff --git a/ncd/tests/backtracking.ncd b/ncd/tests/backtracking.ncd index c239df8..7e291a4 100644 --- a/ncd/tests/backtracking.ncd +++ b/ncd/tests/backtracking.ncd @@ -52,10 +52,12 @@ template helper1 { } template helper2 { - _caller._caller.flag->set("true"); + val_equal(_caller._caller.flag, "true") a; + assert(a); } template helper3 { - val_equal(_caller.flag, "true") a; + val_equal(_caller.flag, "false") a; assert(a); + _caller.flag->set("true"); } |