Exceptions and Critical Regions

The point of critical regions in your code is that sometimes you have data-base updates or other operations that, once started, must be completed in order to avoid an inconsistent state. In particular, such operations should not be interrupted by a ^C from the keyboard.

In releases of Quintus Prolog prior to release 3.0, library(critical) was provided to allow critical regions to be specified using the predicates begin_critical/0 and end_critical/0. These predicates are still provided, but they should be regarded as obsolete since they do not interact well with exception handling. An exception occurring in between the begin_critical and the end_critical could cause two problems:

  1. the Prolog database could be left in an inconsistent state, and
  2. the critical region would never be exited, so interrupts would be left disabled indefinitely.

To avoid these problems, you should use the new predicates

     critical(Goal)
     critical_on_exception(ErrorCode, Goal, Handler)
     

which library(critical) now provides.

critical/1 runs the specified goal inside a critical region. It solves (2) by catching any exceptions that are raised and taking care to close the critical region before re-raising the exception.

critical_on_exception/3 allows you to solve (1) by specifying appropriate clean-up actions in Handler. If an exception occurs during Goal, and the exception code unifies with ErrorCode, critical_on_exception/3 acts as if you had written

     critical(Handler)
     

instead. That is, the Handler will still be inside the critical region, and only the first solution it returns will be taken.

These forms also have the effect of committing to the first solution of Goal. Since the point of a critical region is to ensure that some operation with side-effects is completed, Goal should be determinate anyway, so this should be no problem.