bag_of_all_servant(?Template, +Goal, -Bag)

If the servant is running on a different physical processor than the master, then it is desirable to be able to achieve some degree of parallelism, to have both machines doing useful work at the same time. This is not the case with call_servant/1, since the master Prolog process is waiting the entire time that the servant process is computing. The predicate bag_of_all_servant/3 is provided to allow a sophisticated user to write some truly parallel applications. (See the demo program queensdemo for an example of using parallelism in a search problem.)

Semantically bag_of_all_servant/3 is very similar to bagof/3. The reader should be familiar with the operation of bagof/3 before reading further. The differences are:

  1. bag_of_all_servant/3 requires that there be no free variables in Goal that do not appear in Template. If there are, bag_of_all_servant/3 will report an error. You may use the existential operator (^) as in bagof/3.
  2. bag_of_all_servant/3 succeeds with Bag bound to [] if Goal has no answers at all. This means that bag_of_all_servant/3 always succeeds and returns in Bag exactly one answer: the list of instances of Template, one instance for each success of Goal.

The exact operation of bag_of_all_servant/3 depends on the form of Goal. If Goal is a conjunction of the form (Goal1, Goal2) or a disjunction of the form (Goal1; Goal2), then the first subgoal (Goal1) will be executed by the servant, and the second subgoal (Goal2) will be executed by the current process. The system will try to overlap local and remote evaluation as much as possible. If Goal is neither a conjunction nor a disjunction, then the entire goal will be sent to the servant to be executed.

There are several restrictions on how bag_of_all_servant/3 can be used.