The following examples present some simple CTR programs and their execution. They are executed using XSB Prolog, with the CTR prototype already loaded.
Database file interleave2.db:
Transaction file interleave2.ctr:
parent :- process(a) # process(b).
process(I) :- task(I,1) * task(I,2) * task(I,3).
task(I,J) :- monitor(task(I,J)).
|?-ctr_comp(interleave2). | - program is compiled |
and optimized | |
yes | |
| ?- exec(parent). | - execution of parent goal |
committing task(a,1) | - first task of process(a) commits |
committing task(b,1) | - first task of process(b) commits |
committing task(a,2) | - second task of process(a) commits |
committing task(b,2) | - second task of process(b) commits |
committing task(a,3) | - third task of process(a) commits |
committing task(b,3) | - third task of process(b) commits |
yes |
Database file interleave2a.db:
Transaction file interleave2a.ctr:
parent :- process(a) # o(process(b)).
process(I) :- task(I,1) * task(I,2) * task(I,3).
task(I,J) :- monitor(task(I,J)).
| ?- ctr_comp(interleave2a). | - program is compiled and optimized |
yes
| ?- exec(parent). | - execution of parent goal |
committing task(a,1) | - process(a) starts executing |
committing task(b,1) | - complete execution of |
committing task(b,2) | process(b) in isolation |
committing task(b,3) | |
committing task(a,2) | - process(a) continues its execution |
committing task(a,3) |
yes
Database file disjunction.db:
Transaction file disjunction.ctr:
choose :- (monitor(a1) * monitor(a2) * monitor(a3))
\/ (monitor(b1) * monitor(b2) * monitor(b3)).
| ?- ctr_comp(disjunction). | - program is compiled and optimized |
yes
| ?- exec(choose). | - execution of choose goal |
committing a1 | - display from monitor showing |
committing a2 | that the ai are commited |
committing a3 |
yes
Note the use of fail in the next XSB session, to show that backtracking takes place when an execution is unsuccessful. It forces both processes to be tried.
| ?- exec(choose),fail. | - choose will be forced to fail |
committing a1 | - the ai are committed |
committing a2 | |
committing a3 | |
undoing a3 | - the ai are rolled back |
undoing a2 | |
undoing a1 | |
committing b1 | - the bi are committed |
committing b2 | |
committing b3 | |
undoing b3 | - the bi are rolled back |
undoing b2 | |
undoing b1 | |
no | - all execution schedules have failed |
Database file synchro.db:
updatable start/1.
Transaction file synchro.ctr:
parent :- process(a) # process(b).
process(a) :- task(a1) * task(a2) * task(a3) * task(a4)
* start(a7) * task(a7) * task(a8).
* task(b3) * task(b4) * task(b5) * task(b6)
* ins(start(a7)) * task(b7) * task(b8).
task(I) :- monitor(task(I)).
Note that the database file declares the predicate start as updatable, so it can be updated by the rules in the transaction base file. Since the database file is not empty, it is compiled in the following XSB session.
| ?- ctr_comp(synchro). | - program is compiled and optimized |
yes
| ?- exec(parent). | - execution of parent goal |
committing task(a1) | - process(a) alternates with process(b) |
committing task(b1) | |
committing task(a2) | |
committing task(b2) | |
committing task(a3) | - process(b) waits for start(b3) to be |
committing task(a4) | inserted into the database |
committing task(a5) | |
committing task(a6) | |
committing task(b3) | |
committing task(b4) | - process(a) waits for start(a7) to be |
committing task(b5) | inserted into the database |
committing task(b6) | |
committing task(b7) | - process(a) alternates with process(b) again |
committing task(a7) | |
committing task(b8) | |
committing task(a8) |
yes