1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2019, VU University Amsterdam 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 13 1. Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 POSSIBILITY OF SUCH DAMAGE. 33*/ 34 35:- module(timed_call, 36 [ timed_call/2 37 ]). 38:- use_module(library(time)). 39:- use_module(library(debug)). 40:- use_module(library(error)).
Options is a list of the terms below. At least one of the terms max/2 or repeating/2 must be present.
nesting
, a nested call raises a
permission_error
exception.79:- meta_predicate 80 timed_call( , ). 81 82timed_call(Goal, _Options) :- 83 ok_nested(Goal), 84 !, 85 debug(timed_call, 'Calling nested ~p', [Goal]), 86 once(Goal). 87timed_call(Goal, Options) :- 88 '$timed_call_nested'(Goal, Options), 89 no_lco. 90 91no_lco. 92 93ok_nested(Goal) :- 94 prolog_current_frame(Fr), 95 prolog_frame_attribute(Fr, parent, Fr2), 96 prolog_frame_attribute(Fr2, parent, Parent), 97 prolog_frame_attribute(Parent, parent_goal, 98 timed_call:timed_call(_,_:Options)), 99 !, 100 debug(timed_call, 'Nested ~p: found parent timed call with options ~p', 101 [Goal, Options]), 102 ( memberchk(nesting, Options) 103 -> true 104 ; permission_error(nest, timed_goal, Goal) 105 ). 106 107 108'$timed_call_nested'(Goal, M:Options) :- 109 memberchk(max(MaxInterval, MaxHandler), Options), 110 !, 111 run_max_goal(Goal, MaxInterval, MaxHandler, M:Options). 112'$timed_call_nested'(Goal, M:Options) :- 113 memberchk(repeating(RepInterval, RepHandler), Options), 114 !, 115 run_repeating_goal(Goal, RepInterval, RepHandler, M:Options). 116'$timed_call_nested'(_Goal, _M:Options) :- 117 domain_error(timed_call_options, Options). 118 119run_max_goal(Goal, MaxInterval, MaxHandler, M:Options) :- 120 ( MaxInterval > 0 121 -> Time is MaxInterval/1000, 122 setup_call_cleanup(alarm(Time, ignore(M:MaxHandler), 123 Id, [install(false)]), 124 run_opt_releating(Id, Goal, M:Options), 125 time:remove_alarm_notrace(Id)) 126 ; call(M:MaxHandler) 127 ). 128 129run_opt_releating(AlarmID, Goal, M:Options) :- 130 memberchk(repeating(RepInterval, RepHandler), Options), 131 !, 132 install_alarm(AlarmID), 133 run_repeating_goal(Goal, RepInterval, RepHandler, M:Options). 134run_opt_releating(AlarmID, Goal, _Options) :- 135 install_alarm(AlarmID), 136 call(Goal), 137 !. 138 139run_repeating_goal(Goal, RepInterval, RepHandler, M:_Options) :- 140 ( RepInterval > 0 141 -> Time is RepInterval/1000, 142 setup_call_cleanup(alarm(Time, repeat_handler(Id, Time, M:RepHandler), 143 Id, [install(false)]), 144 run_alarm_goal(Id, Goal), 145 time:remove_alarm_notrace(Id)) 146 ; domain_error(repeating_interval, RepInterval) 147 ). 148 149 150repeat_handler(Id, Time, M:RepHandler) :- 151 ignore(M:RepHandler), 152 uninstall_alarm(Id), 153 install_alarm(Id, Time). 154 155run_alarm_goal(AlarmID, Goal) :- 156 install_alarm(AlarmID), 157 call(Goal), 158 !
XSB timed call
This module emulates the XSB built-in timed_call/2. As this is a built-in, this module is re-exported from library(dialect/xsb). It has been placed in a separete module to facilitate reuse and allow to not load this if the prerequisites (library(time) and multi-threading) are not satisfied. */