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)).
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.77:- meta_predicate 78 timed_call( , ). 79 80timed_call(Goal, _Options) :- 81 ok_nested(Goal), 82 !, 83 debug(timed_call, 'Calling nested ~p', [Goal]), 84 once(Goal). 85timed_call(Goal, Options) :- 86 '$timed_call_nested'(Goal, Options), 87 no_lco. 88 89no_lco. 90 91ok_nested(Goal) :- 92 prolog_current_frame(Fr), 93 prolog_frame_attribute(Fr, parent, Fr2), 94 prolog_frame_attribute(Fr2, parent, Parent), 95 prolog_frame_attribute(Parent, parent_goal, 96 timed_call:timed_call(_,_:Options)), 97 !, 98 debug(timed_call, 'Nested ~p: found parent timed call with options ~p', 99 [Goal, Options]), 100 ( memberchk(nesting, Options) 101 -> true 102 ; permission_error(nest, timed_goal, Goal) 103 ). 104 105 106'$timed_call_nested'(Goal, M:Options) :- 107 memberchk(max(MaxInterval, MaxHandler), Options), 108 !, 109 run_max_goal(Goal, MaxInterval, MaxHandler, M:Options). 110'$timed_call_nested'(Goal, M:Options) :- 111 memberchk(repeating(RepInterval, RepHandler), Options), 112 !, 113 run_repeating_goal(Goal, RepInterval, RepHandler, M:Options). 114'$timed_call_nested'(_Goal, _M:Options) :- 115 domain_error(timed_call_options, Options). 116 117run_max_goal(Goal, MaxInterval, MaxHandler, M:Options) :- 118 ( MaxInterval > 0 119 -> Time is MaxInterval/1000, 120 setup_call_cleanup(alarm(Time, ignore(M:MaxHandler), 121 Id, [install(false)]), 122 run_opt_releating(Id, Goal, M:Options), 123 time:remove_alarm_notrace(Id)) 124 ; call(M:MaxHandler) 125 ). 126 127run_opt_releating(AlarmID, Goal, M:Options) :- 128 memberchk(repeating(RepInterval, RepHandler), Options), 129 !, 130 install_alarm(AlarmID), 131 run_repeating_goal(Goal, RepInterval, RepHandler, M:Options). 132run_opt_releating(AlarmID, Goal, _Options) :- 133 install_alarm(AlarmID), 134 call(Goal), 135 !. 136 137run_repeating_goal(Goal, RepInterval, RepHandler, M:_Options) :- 138 ( RepInterval > 0 139 -> Time is RepInterval/1000, 140 setup_call_cleanup(alarm(Time, repeat_handler(Id, Time, M:RepHandler), 141 Id, [install(false)]), 142 run_alarm_goal(Id, Goal), 143 time:remove_alarm_notrace(Id)) 144 ; domain_error(repeating_interval, RepInterval) 145 ). 146 147 148repeat_handler(Id, Time, M:RepHandler) :- 149 ignore(M:RepHandler), 150 uninstall_alarm(Id), 151 install_alarm(Id, Time). 152 153run_alarm_goal(AlarmID, Goal) :- 154 install_alarm(AlarmID), 155 call(Goal), 156 !
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. */