kibi-swipl-linux-x64-gnu 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (550) hide show
  1. package/README.md +29 -0
  2. package/bin/swipl +0 -0
  3. package/bin/swipl-win +0 -0
  4. package/build-manifest.json +70 -0
  5. package/lib/cmake/swipl/SWIPLConfig.cmake +21 -0
  6. package/lib/cmake/swipl/SWIPLConfigVersion.cmake +65 -0
  7. package/lib/cmake/swipl/SWIPLTargets-release.cmake +28 -0
  8. package/lib/cmake/swipl/SWIPLTargets.cmake +109 -0
  9. package/lib/swipl/ABI +1 -0
  10. package/lib/swipl/LICENSE +41 -0
  11. package/lib/swipl/README.md +116 -0
  12. package/lib/swipl/app/README.md +25 -0
  13. package/lib/swipl/app/app.pl +87 -0
  14. package/lib/swipl/app/pack.pl +350 -0
  15. package/lib/swipl/app/qlf.pl +521 -0
  16. package/lib/swipl/app/splfr.pl +177 -0
  17. package/lib/swipl/app/sys.pl +310 -0
  18. package/lib/swipl/bin/swipl.home +1 -0
  19. package/lib/swipl/boot/apply.pl +73 -0
  20. package/lib/swipl/boot/attvar.pl +344 -0
  21. package/lib/swipl/boot/autoload.pl +1226 -0
  22. package/lib/swipl/boot/bags.pl +283 -0
  23. package/lib/swipl/boot/dcg.pl +388 -0
  24. package/lib/swipl/boot/dicts.pl +193 -0
  25. package/lib/swipl/boot/dwim.pl +485 -0
  26. package/lib/swipl/boot/engines.pl +152 -0
  27. package/lib/swipl/boot/expand.pl +1628 -0
  28. package/lib/swipl/boot/gc.pl +65 -0
  29. package/lib/swipl/boot/history.pl +304 -0
  30. package/lib/swipl/boot/init.pl +4682 -0
  31. package/lib/swipl/boot/iri.pl +64 -0
  32. package/lib/swipl/boot/license.pl +390 -0
  33. package/lib/swipl/boot/load.pl +81 -0
  34. package/lib/swipl/boot/messages.pl +2521 -0
  35. package/lib/swipl/boot/packs.pl +306 -0
  36. package/lib/swipl/boot/predopts.pl +154 -0
  37. package/lib/swipl/boot/qlf.pl +141 -0
  38. package/lib/swipl/boot/rc.pl +263 -0
  39. package/lib/swipl/boot/syspred.pl +1634 -0
  40. package/lib/swipl/boot/tabling.pl +2321 -0
  41. package/lib/swipl/boot/threads.pl +42 -0
  42. package/lib/swipl/boot/toplevel.pl +2248 -0
  43. package/lib/swipl/boot/topvars.pl +261 -0
  44. package/lib/swipl/boot.prc +0 -0
  45. package/lib/swipl/cmake/swipl.cmake +131 -0
  46. package/lib/swipl/customize/README.md +23 -0
  47. package/lib/swipl/customize/edit +101 -0
  48. package/lib/swipl/customize/init.pl +164 -0
  49. package/lib/swipl/demo/README.md +33 -0
  50. package/lib/swipl/demo/likes.pl +44 -0
  51. package/lib/swipl/doc/packages/examples/chr/bool.chr +281 -0
  52. package/lib/swipl/doc/packages/examples/chr/chrdif.chr +87 -0
  53. package/lib/swipl/doc/packages/examples/chr/chrfreeze.chr +6 -0
  54. package/lib/swipl/doc/packages/examples/chr/family.chr +116 -0
  55. package/lib/swipl/doc/packages/examples/chr/fib.chr +24 -0
  56. package/lib/swipl/doc/packages/examples/chr/fibonacci.chr +31 -0
  57. package/lib/swipl/doc/packages/examples/chr/gcd.chr +28 -0
  58. package/lib/swipl/doc/packages/examples/chr/leq.chr +34 -0
  59. package/lib/swipl/doc/packages/examples/chr/listdom.chr +138 -0
  60. package/lib/swipl/doc/packages/examples/chr/primes.chr +29 -0
  61. package/lib/swipl/doc/packages/examples/http/README.md +98 -0
  62. package/lib/swipl/doc/packages/examples/http/calc.pl +92 -0
  63. package/lib/swipl/doc/packages/examples/http/demo_body.pl +232 -0
  64. package/lib/swipl/doc/packages/examples/http/demo_client.pl +165 -0
  65. package/lib/swipl/doc/packages/examples/http/demo_daemon.pl +38 -0
  66. package/lib/swipl/doc/packages/examples/http/demo_files.pl +50 -0
  67. package/lib/swipl/doc/packages/examples/http/demo_hello.pl +15 -0
  68. package/lib/swipl/doc/packages/examples/http/demo_login.pl +280 -0
  69. package/lib/swipl/doc/packages/examples/http/demo_openid.pl +177 -0
  70. package/lib/swipl/doc/packages/examples/http/demo_pwp.pl +20 -0
  71. package/lib/swipl/doc/packages/examples/http/demo_rest.pl +56 -0
  72. package/lib/swipl/doc/packages/examples/http/demo_threads.pl +52 -0
  73. package/lib/swipl/doc/packages/examples/http/linux-init-script +126 -0
  74. package/lib/swipl/doc/packages/examples/http/pwp/context.pwp +23 -0
  75. package/lib/swipl/doc/packages/examples/http/pwp/index.pwp +25 -0
  76. package/lib/swipl/doc/packages/examples/http/pwp/pwp1.pwp +12 -0
  77. package/lib/swipl/doc/packages/examples/http/pwp/pwp2.pwp +10 -0
  78. package/lib/swipl/doc/packages/examples/http/pwp/pwp3.pwp +25 -0
  79. package/lib/swipl/doc/packages/examples/http/pwp/pwp4.pwp +23 -0
  80. package/lib/swipl/doc/packages/examples/http/pwp/pwp5.pwp +11 -0
  81. package/lib/swipl/doc/packages/examples/http/pwp/pwp6.pwp +3 -0
  82. package/lib/swipl/doc/packages/examples/http/pwp/pwp7.pwp +3 -0
  83. package/lib/swipl/doc/packages/examples/http/pwp/pwp8.pwp +3 -0
  84. package/lib/swipl/doc/packages/examples/http/pwp/pwpdb.pl +12 -0
  85. package/lib/swipl/doc/packages/examples/http/systemd-script.service +18 -0
  86. package/lib/swipl/doc/packages/examples/http/upstart-script.conf +20 -0
  87. package/lib/swipl/doc/packages/examples/plunit/read.pl +17 -0
  88. package/lib/swipl/doc/packages/examples/plunit/simple.pl +33 -0
  89. package/lib/swipl/doc/packages/examples/ssl/client.pl +83 -0
  90. package/lib/swipl/doc/packages/examples/ssl/etc/README +52 -0
  91. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-cert.p12 +0 -0
  92. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-cert.pem +85 -0
  93. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-key.pem +30 -0
  94. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/cacert.pem +82 -0
  95. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/careq.pem +18 -0
  96. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/crlnumber +1 -0
  97. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/index.txt +3 -0
  98. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/index.txt.attr +1 -0
  99. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/newcerts/9DC08797A0F63F7C.pem +85 -0
  100. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/newcerts/9DC08797A0F63F7D.pem +85 -0
  101. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/private/cakey.pem +30 -0
  102. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/serial +1 -0
  103. package/lib/swipl/doc/packages/examples/ssl/etc/server/server-cert.pem +85 -0
  104. package/lib/swipl/doc/packages/examples/ssl/etc/server/server-key.pem +30 -0
  105. package/lib/swipl/doc/packages/examples/ssl/https.pl +267 -0
  106. package/lib/swipl/doc/packages/examples/ssl/server.pl +106 -0
  107. package/lib/swipl/include/SWI-Prolog.h +1544 -0
  108. package/lib/swipl/include/SWI-Stream.h +537 -0
  109. package/lib/swipl/include/Yap/YapInterface.h +283 -0
  110. package/lib/swipl/include/sicstus/sicstus.h +452 -0
  111. package/lib/swipl/lib/x86_64-linux/cgi.so +0 -0
  112. package/lib/swipl/lib/x86_64-linux/crypt.so +0 -0
  113. package/lib/swipl/lib/x86_64-linux/crypto4pl.so +0 -0
  114. package/lib/swipl/lib/x86_64-linux/double_metaphone.so +0 -0
  115. package/lib/swipl/lib/x86_64-linux/files.so +0 -0
  116. package/lib/swipl/lib/x86_64-linux/hashstream.so +0 -0
  117. package/lib/swipl/lib/x86_64-linux/http_stream.so +0 -0
  118. package/lib/swipl/lib/x86_64-linux/isub.so +0 -0
  119. package/lib/swipl/lib/x86_64-linux/json.so +0 -0
  120. package/lib/swipl/lib/x86_64-linux/libswipl.so.10 +0 -0
  121. package/lib/swipl/lib/x86_64-linux/mallocinfo.so +0 -0
  122. package/lib/swipl/lib/x86_64-linux/md54pl.so +0 -0
  123. package/lib/swipl/lib/x86_64-linux/memfile.so +0 -0
  124. package/lib/swipl/lib/x86_64-linux/ntriples.so +0 -0
  125. package/lib/swipl/lib/x86_64-linux/pcre4pl.so +0 -0
  126. package/lib/swipl/lib/x86_64-linux/porter_stem.so +0 -0
  127. package/lib/swipl/lib/x86_64-linux/process.so +0 -0
  128. package/lib/swipl/lib/x86_64-linux/prolog_stream.so +0 -0
  129. package/lib/swipl/lib/x86_64-linux/rdf_db.so +0 -0
  130. package/lib/swipl/lib/x86_64-linux/readutil.so +0 -0
  131. package/lib/swipl/lib/x86_64-linux/rlimit.so +0 -0
  132. package/lib/swipl/lib/x86_64-linux/sched.so +0 -0
  133. package/lib/swipl/lib/x86_64-linux/sgml2pl.so +0 -0
  134. package/lib/swipl/lib/x86_64-linux/sha4pl.so +0 -0
  135. package/lib/swipl/lib/x86_64-linux/snowball.so +0 -0
  136. package/lib/swipl/lib/x86_64-linux/socket.so +0 -0
  137. package/lib/swipl/lib/x86_64-linux/ssl4pl.so +0 -0
  138. package/lib/swipl/lib/x86_64-linux/streaminfo.so +0 -0
  139. package/lib/swipl/lib/x86_64-linux/syslog.so +0 -0
  140. package/lib/swipl/lib/x86_64-linux/time.so +0 -0
  141. package/lib/swipl/lib/x86_64-linux/turtle.so +0 -0
  142. package/lib/swipl/lib/x86_64-linux/uid.so +0 -0
  143. package/lib/swipl/lib/x86_64-linux/unix.so +0 -0
  144. package/lib/swipl/lib/x86_64-linux/uri.so +0 -0
  145. package/lib/swipl/lib/x86_64-linux/websocket.so +0 -0
  146. package/lib/swipl/lib/x86_64-linux/zlib4pl.so +0 -0
  147. package/lib/swipl/library/INDEX.pl +1020 -0
  148. package/lib/swipl/library/aggregate.pl +755 -0
  149. package/lib/swipl/library/ansi_term.pl +653 -0
  150. package/lib/swipl/library/apply.pl +426 -0
  151. package/lib/swipl/library/apply_macros.pl +497 -0
  152. package/lib/swipl/library/arithmetic.pl +320 -0
  153. package/lib/swipl/library/assoc.pl +522 -0
  154. package/lib/swipl/library/atom.pl +169 -0
  155. package/lib/swipl/library/backcomp.pl +688 -0
  156. package/lib/swipl/library/base32.pl +291 -0
  157. package/lib/swipl/library/base64.pl +441 -0
  158. package/lib/swipl/library/broadcast.pl +161 -0
  159. package/lib/swipl/library/build/cmake.pl +137 -0
  160. package/lib/swipl/library/build/conan.pl +232 -0
  161. package/lib/swipl/library/build/make.pl +168 -0
  162. package/lib/swipl/library/build/tools.pl +825 -0
  163. package/lib/swipl/library/charsio.pl +195 -0
  164. package/lib/swipl/library/check.pl +1097 -0
  165. package/lib/swipl/library/check_installation.pl +912 -0
  166. package/lib/swipl/library/clp/INDEX.pl +157 -0
  167. package/lib/swipl/library/clp/bounds.pl +2036 -0
  168. package/lib/swipl/library/clp/clp_distinct.pl +263 -0
  169. package/lib/swipl/library/clp/clp_events.pl +92 -0
  170. package/lib/swipl/library/clp/clpb.pl +1896 -0
  171. package/lib/swipl/library/clp/clpfd.pl +7906 -0
  172. package/lib/swipl/library/clp/simplex.pl +1580 -0
  173. package/lib/swipl/library/codesio.pl +182 -0
  174. package/lib/swipl/library/coinduction.pl +183 -0
  175. package/lib/swipl/library/console_input.pl +289 -0
  176. package/lib/swipl/library/csv.pl +611 -0
  177. package/lib/swipl/library/ctypes.pl +161 -0
  178. package/lib/swipl/library/date.pl +370 -0
  179. package/lib/swipl/library/dcg/INDEX.pl +35 -0
  180. package/lib/swipl/library/dcg/basics.pl +514 -0
  181. package/lib/swipl/library/dcg/high_order.pl +227 -0
  182. package/lib/swipl/library/debug.pl +499 -0
  183. package/lib/swipl/library/dialect/bim.pl +186 -0
  184. package/lib/swipl/library/dialect/commons.pl +77 -0
  185. package/lib/swipl/library/dialect/eclipse/test_util_iso.pl +355 -0
  186. package/lib/swipl/library/dialect/hprolog/format.pl +44 -0
  187. package/lib/swipl/library/dialect/hprolog.pl +314 -0
  188. package/lib/swipl/library/dialect/ifprolog.pl +1317 -0
  189. package/lib/swipl/library/dialect/iso/iso_predicates.pl +277 -0
  190. package/lib/swipl/library/dialect/sicstus/README.TXT +1 -0
  191. package/lib/swipl/library/dialect/sicstus/arrays.pl +121 -0
  192. package/lib/swipl/library/dialect/sicstus/block.pl +278 -0
  193. package/lib/swipl/library/dialect/sicstus/lists.pl +167 -0
  194. package/lib/swipl/library/dialect/sicstus/ordsets.pl +52 -0
  195. package/lib/swipl/library/dialect/sicstus/sockets.pl +174 -0
  196. package/lib/swipl/library/dialect/sicstus/system.pl +262 -0
  197. package/lib/swipl/library/dialect/sicstus/terms.pl +57 -0
  198. package/lib/swipl/library/dialect/sicstus/timeout.pl +92 -0
  199. package/lib/swipl/library/dialect/sicstus.pl +582 -0
  200. package/lib/swipl/library/dialect/sicstus4/aggregate.pl +60 -0
  201. package/lib/swipl/library/dialect/sicstus4/between.pl +62 -0
  202. package/lib/swipl/library/dialect/sicstus4/clpfd.pl +75 -0
  203. package/lib/swipl/library/dialect/sicstus4/file_systems.pl +413 -0
  204. package/lib/swipl/library/dialect/sicstus4/lists.pl +274 -0
  205. package/lib/swipl/library/dialect/sicstus4/ordsets.pl +54 -0
  206. package/lib/swipl/library/dialect/sicstus4/samsort.pl +86 -0
  207. package/lib/swipl/library/dialect/sicstus4/sets.pl +124 -0
  208. package/lib/swipl/library/dialect/sicstus4/sockets.pl +164 -0
  209. package/lib/swipl/library/dialect/sicstus4/system.pl +80 -0
  210. package/lib/swipl/library/dialect/sicstus4/terms.pl +89 -0
  211. package/lib/swipl/library/dialect/sicstus4/timeout.pl +43 -0
  212. package/lib/swipl/library/dialect/sicstus4/types.pl +103 -0
  213. package/lib/swipl/library/dialect/sicstus4.pl +200 -0
  214. package/lib/swipl/library/dialect/swi/syspred_options.pl +250 -0
  215. package/lib/swipl/library/dialect/xsb/README.md +20 -0
  216. package/lib/swipl/library/dialect/xsb/basics.pl +318 -0
  217. package/lib/swipl/library/dialect/xsb/consult.pl +87 -0
  218. package/lib/swipl/library/dialect/xsb/curr_sym.pl +57 -0
  219. package/lib/swipl/library/dialect/xsb/error_handler.pl +111 -0
  220. package/lib/swipl/library/dialect/xsb/gensym.pl +53 -0
  221. package/lib/swipl/library/dialect/xsb/gpp.pl +138 -0
  222. package/lib/swipl/library/dialect/xsb/intern.pl +48 -0
  223. package/lib/swipl/library/dialect/xsb/lists.pl +47 -0
  224. package/lib/swipl/library/dialect/xsb/machine.pl +295 -0
  225. package/lib/swipl/library/dialect/xsb/ordsets.pl +53 -0
  226. package/lib/swipl/library/dialect/xsb/setof.pl +54 -0
  227. package/lib/swipl/library/dialect/xsb/source.pl +308 -0
  228. package/lib/swipl/library/dialect/xsb/standard.pl +169 -0
  229. package/lib/swipl/library/dialect/xsb/storage.pl +70 -0
  230. package/lib/swipl/library/dialect/xsb/string.pl +76 -0
  231. package/lib/swipl/library/dialect/xsb/thread.pl +62 -0
  232. package/lib/swipl/library/dialect/xsb/timed_call.pl +158 -0
  233. package/lib/swipl/library/dialect/xsb.pl +688 -0
  234. package/lib/swipl/library/dialect/yap/README.TXT +8 -0
  235. package/lib/swipl/library/dialect/yap.pl +283 -0
  236. package/lib/swipl/library/dialect.pl +123 -0
  237. package/lib/swipl/library/dicts.pl +399 -0
  238. package/lib/swipl/library/dif.pl +426 -0
  239. package/lib/swipl/library/edinburgh.pl +138 -0
  240. package/lib/swipl/library/edit.pl +783 -0
  241. package/lib/swipl/library/error.pl +495 -0
  242. package/lib/swipl/library/exceptions.pl +231 -0
  243. package/lib/swipl/library/explain.pl +543 -0
  244. package/lib/swipl/library/ext/RDF/INDEX.pl +25 -0
  245. package/lib/swipl/library/ext/RDF/rdf.pl +450 -0
  246. package/lib/swipl/library/ext/RDF/rdf_parser.pl +649 -0
  247. package/lib/swipl/library/ext/RDF/rdf_triple.pl +448 -0
  248. package/lib/swipl/library/ext/RDF/rdf_write.pl +701 -0
  249. package/lib/swipl/library/ext/RDF/rewrite_term.pl +177 -0
  250. package/lib/swipl/library/ext/chr/chr/a_star.pl +80 -0
  251. package/lib/swipl/library/ext/chr/chr/binomialheap.pl +142 -0
  252. package/lib/swipl/library/ext/chr/chr/builtins.pl +629 -0
  253. package/lib/swipl/library/ext/chr/chr/chr_compiler_errors.pl +179 -0
  254. package/lib/swipl/library/ext/chr/chr/chr_compiler_options.pl +382 -0
  255. package/lib/swipl/library/ext/chr/chr/chr_compiler_utility.pl +338 -0
  256. package/lib/swipl/library/ext/chr/chr/chr_debug.pl +59 -0
  257. package/lib/swipl/library/ext/chr/chr/chr_hashtable_store.pl +425 -0
  258. package/lib/swipl/library/ext/chr/chr/chr_integertable_store.pl +139 -0
  259. package/lib/swipl/library/ext/chr/chr/chr_messages.pl +176 -0
  260. package/lib/swipl/library/ext/chr/chr/chr_op.pl +53 -0
  261. package/lib/swipl/library/ext/chr/chr/chr_runtime.pl +1016 -0
  262. package/lib/swipl/library/ext/chr/chr/chr_translate.pl +25424 -0
  263. package/lib/swipl/library/ext/chr/chr/clean_code.pl +252 -0
  264. package/lib/swipl/library/ext/chr/chr/find.pl +78 -0
  265. package/lib/swipl/library/ext/chr/chr/guard_entailment.pl +19432 -0
  266. package/lib/swipl/library/ext/chr/chr/listmap.pl +108 -0
  267. package/lib/swipl/library/ext/chr/chr/pairlist.pl +78 -0
  268. package/lib/swipl/library/ext/chr/chr.pl +686 -0
  269. package/lib/swipl/library/ext/clib/INDEX.pl +158 -0
  270. package/lib/swipl/library/ext/clib/cgi.pl +86 -0
  271. package/lib/swipl/library/ext/clib/crypt.pl +44 -0
  272. package/lib/swipl/library/ext/clib/filesex.pl +644 -0
  273. package/lib/swipl/library/ext/clib/hash_stream.pl +119 -0
  274. package/lib/swipl/library/ext/clib/mallocinfo.pl +138 -0
  275. package/lib/swipl/library/ext/clib/md5.pl +68 -0
  276. package/lib/swipl/library/ext/clib/memfile.pl +61 -0
  277. package/lib/swipl/library/ext/clib/process.pl +573 -0
  278. package/lib/swipl/library/ext/clib/prolog_server.pl +157 -0
  279. package/lib/swipl/library/ext/clib/prolog_stream.pl +80 -0
  280. package/lib/swipl/library/ext/clib/rlimit.pl +54 -0
  281. package/lib/swipl/library/ext/clib/sched.pl +85 -0
  282. package/lib/swipl/library/ext/clib/sha.pl +162 -0
  283. package/lib/swipl/library/ext/clib/socket.pl +1102 -0
  284. package/lib/swipl/library/ext/clib/streaminfo.pl +103 -0
  285. package/lib/swipl/library/ext/clib/streampool.pl +136 -0
  286. package/lib/swipl/library/ext/clib/syslog.pl +180 -0
  287. package/lib/swipl/library/ext/clib/time.pl +194 -0
  288. package/lib/swipl/library/ext/clib/udp_broadcast.pl +975 -0
  289. package/lib/swipl/library/ext/clib/uid.pl +220 -0
  290. package/lib/swipl/library/ext/clib/unix.pl +317 -0
  291. package/lib/swipl/library/ext/clib/uri.pl +530 -0
  292. package/lib/swipl/library/ext/clib/uuid.pl +207 -0
  293. package/lib/swipl/library/ext/http/http/INDEX.pl +266 -0
  294. package/lib/swipl/library/ext/http/http/README.md +34 -0
  295. package/lib/swipl/library/ext/http/http/ax.pl +189 -0
  296. package/lib/swipl/library/ext/http/http/dcg_basics.pl +49 -0
  297. package/lib/swipl/library/ext/http/http/graphql.pl +1367 -0
  298. package/lib/swipl/library/ext/http/http/html_decl.pl +416 -0
  299. package/lib/swipl/library/ext/http/http/html_head.pl +654 -0
  300. package/lib/swipl/library/ext/http/http/html_quasiquotations.pl +120 -0
  301. package/lib/swipl/library/ext/http/http/html_write.pl +1425 -0
  302. package/lib/swipl/library/ext/http/http/htmx.pl +139 -0
  303. package/lib/swipl/library/ext/http/http/http_authenticate.pl +364 -0
  304. package/lib/swipl/library/ext/http/http/http_client.pl +412 -0
  305. package/lib/swipl/library/ext/http/http/http_cookie.pl +245 -0
  306. package/lib/swipl/library/ext/http/http/http_cors.pl +176 -0
  307. package/lib/swipl/library/ext/http/http/http_digest.pl +820 -0
  308. package/lib/swipl/library/ext/http/http/http_dirindex.pl +296 -0
  309. package/lib/swipl/library/ext/http/http/http_dispatch.pl +1552 -0
  310. package/lib/swipl/library/ext/http/http/http_dyn_workers.pl +214 -0
  311. package/lib/swipl/library/ext/http/http/http_error.pl +126 -0
  312. package/lib/swipl/library/ext/http/http/http_exception.pl +225 -0
  313. package/lib/swipl/library/ext/http/http/http_files.pl +163 -0
  314. package/lib/swipl/library/ext/http/http/http_header.pl +2820 -0
  315. package/lib/swipl/library/ext/http/http/http_hook.pl +106 -0
  316. package/lib/swipl/library/ext/http/http/http_host.pl +204 -0
  317. package/lib/swipl/library/ext/http/http/http_load.pl +113 -0
  318. package/lib/swipl/library/ext/http/http/http_log.pl +738 -0
  319. package/lib/swipl/library/ext/http/http/http_multipart_plugin.pl +232 -0
  320. package/lib/swipl/library/ext/http/http/http_open.pl +1821 -0
  321. package/lib/swipl/library/ext/http/http/http_openid.pl +1561 -0
  322. package/lib/swipl/library/ext/http/http/http_parameters.pl +504 -0
  323. package/lib/swipl/library/ext/http/http/http_path.pl +380 -0
  324. package/lib/swipl/library/ext/http/http/http_proxy.pl +80 -0
  325. package/lib/swipl/library/ext/http/http/http_pwp.pl +351 -0
  326. package/lib/swipl/library/ext/http/http/http_redis_plugin.pl +332 -0
  327. package/lib/swipl/library/ext/http/http/http_server.pl +105 -0
  328. package/lib/swipl/library/ext/http/http/http_server_files.pl +126 -0
  329. package/lib/swipl/library/ext/http/http/http_server_health.pl +186 -0
  330. package/lib/swipl/library/ext/http/http/http_session.pl +1040 -0
  331. package/lib/swipl/library/ext/http/http/http_sgml_plugin.pl +137 -0
  332. package/lib/swipl/library/ext/http/http/http_stream.pl +376 -0
  333. package/lib/swipl/library/ext/http/http/http_unix_daemon.pl +989 -0
  334. package/lib/swipl/library/ext/http/http/http_wrapper.pl +559 -0
  335. package/lib/swipl/library/ext/http/http/hub.pl +600 -0
  336. package/lib/swipl/library/ext/http/http/js_write.pl +461 -0
  337. package/lib/swipl/library/ext/http/http/mimepack.pl +224 -0
  338. package/lib/swipl/library/ext/http/http/mimetype.pl +276 -0
  339. package/lib/swipl/library/ext/http/http/term_html.pl +797 -0
  340. package/lib/swipl/library/ext/http/http/thread_httpd.pl +1181 -0
  341. package/lib/swipl/library/ext/http/http/web/css/dirindex.css +24 -0
  342. package/lib/swipl/library/ext/http/http/web/css/openid.css +57 -0
  343. package/lib/swipl/library/ext/http/http/web/icons/back.png +0 -0
  344. package/lib/swipl/library/ext/http/http/web/icons/c.png +0 -0
  345. package/lib/swipl/library/ext/http/http/web/icons/compressed.png +0 -0
  346. package/lib/swipl/library/ext/http/http/web/icons/folder.png +0 -0
  347. package/lib/swipl/library/ext/http/http/web/icons/generic.png +0 -0
  348. package/lib/swipl/library/ext/http/http/web/icons/layout.png +0 -0
  349. package/lib/swipl/library/ext/http/http/web/icons/openid-logo-square.png +0 -0
  350. package/lib/swipl/library/ext/http/http/web/icons/openid-logo-tiny.png +0 -0
  351. package/lib/swipl/library/ext/http/http/websocket.pl +729 -0
  352. package/lib/swipl/library/ext/http/http/yadis.pl +205 -0
  353. package/lib/swipl/library/ext/json/INDEX.pl +36 -0
  354. package/lib/swipl/library/ext/json/http/INDEX.pl +16 -0
  355. package/lib/swipl/library/ext/json/http/http_json.pl +490 -0
  356. package/lib/swipl/library/ext/json/http/js_grammar.pl +53 -0
  357. package/lib/swipl/library/ext/json/http/json.pl +48 -0
  358. package/lib/swipl/library/ext/json/http/json_convert.pl +48 -0
  359. package/lib/swipl/library/ext/json/json.pl +1215 -0
  360. package/lib/swipl/library/ext/json/json_convert.pl +681 -0
  361. package/lib/swipl/library/ext/json/json_grammar.pl +349 -0
  362. package/lib/swipl/library/ext/json/json_rpc_client.pl +423 -0
  363. package/lib/swipl/library/ext/json/json_rpc_common.pl +104 -0
  364. package/lib/swipl/library/ext/json/json_rpc_server.pl +489 -0
  365. package/lib/swipl/library/ext/json/json_schema.pl +2111 -0
  366. package/lib/swipl/library/ext/nlp/INDEX.pl +15 -0
  367. package/lib/swipl/library/ext/nlp/double_metaphone.pl +86 -0
  368. package/lib/swipl/library/ext/nlp/isub.pl +162 -0
  369. package/lib/swipl/library/ext/nlp/porter_stem.pl +50 -0
  370. package/lib/swipl/library/ext/nlp/snowball.pl +97 -0
  371. package/lib/swipl/library/ext/pcre/INDEX.pl +17 -0
  372. package/lib/swipl/library/ext/pcre/pcre.pl +974 -0
  373. package/lib/swipl/library/ext/plunit/INDEX.pl +20 -0
  374. package/lib/swipl/library/ext/plunit/plunit.pl +2631 -0
  375. package/lib/swipl/library/ext/plunit/test_wizard.pl +249 -0
  376. package/lib/swipl/library/ext/semweb/semweb/INDEX.pl +288 -0
  377. package/lib/swipl/library/ext/semweb/semweb/rdf11.pl +2106 -0
  378. package/lib/swipl/library/ext/semweb/semweb/rdf11_containers.pl +299 -0
  379. package/lib/swipl/library/ext/semweb/semweb/rdf_cache.pl +278 -0
  380. package/lib/swipl/library/ext/semweb/semweb/rdf_compare.pl +132 -0
  381. package/lib/swipl/library/ext/semweb/semweb/rdf_db.pl +3468 -0
  382. package/lib/swipl/library/ext/semweb/semweb/rdf_edit.pl +1145 -0
  383. package/lib/swipl/library/ext/semweb/semweb/rdf_http_plugin.pl +274 -0
  384. package/lib/swipl/library/ext/semweb/semweb/rdf_library.pl +1021 -0
  385. package/lib/swipl/library/ext/semweb/semweb/rdf_litindex.pl +1035 -0
  386. package/lib/swipl/library/ext/semweb/semweb/rdf_ntriples.pl +422 -0
  387. package/lib/swipl/library/ext/semweb/semweb/rdf_persistency.pl +1576 -0
  388. package/lib/swipl/library/ext/semweb/semweb/rdf_portray.pl +182 -0
  389. package/lib/swipl/library/ext/semweb/semweb/rdf_prefixes.pl +681 -0
  390. package/lib/swipl/library/ext/semweb/semweb/rdf_sandbox.pl +153 -0
  391. package/lib/swipl/library/ext/semweb/semweb/rdf_turtle.pl +54 -0
  392. package/lib/swipl/library/ext/semweb/semweb/rdf_turtle_write.pl +1587 -0
  393. package/lib/swipl/library/ext/semweb/semweb/rdf_zlib_plugin.pl +52 -0
  394. package/lib/swipl/library/ext/semweb/semweb/rdfa.pl +1510 -0
  395. package/lib/swipl/library/ext/semweb/semweb/rdfs.pl +475 -0
  396. package/lib/swipl/library/ext/semweb/semweb/sparql_client.pl +643 -0
  397. package/lib/swipl/library/ext/semweb/semweb/turtle.pl +455 -0
  398. package/lib/swipl/library/ext/sgml/DTD/HTML4.dcl +88 -0
  399. package/lib/swipl/library/ext/sgml/DTD/HTML4.dtd +1092 -0
  400. package/lib/swipl/library/ext/sgml/DTD/HTML4.soc +6 -0
  401. package/lib/swipl/library/ext/sgml/DTD/HTML5.dtd +906 -0
  402. package/lib/swipl/library/ext/sgml/DTD/HTMLlat1.ent +195 -0
  403. package/lib/swipl/library/ext/sgml/DTD/HTMLspec.ent +77 -0
  404. package/lib/swipl/library/ext/sgml/DTD/HTMLsym.ent +241 -0
  405. package/lib/swipl/library/ext/sgml/INDEX.pl +64 -0
  406. package/lib/swipl/library/ext/sgml/c14n2.pl +203 -0
  407. package/lib/swipl/library/ext/sgml/iso_639.pl +631 -0
  408. package/lib/swipl/library/ext/sgml/pwp.pl +705 -0
  409. package/lib/swipl/library/ext/sgml/sgml.pl +815 -0
  410. package/lib/swipl/library/ext/sgml/sgml_write.pl +1003 -0
  411. package/lib/swipl/library/ext/sgml/xpath.pl +620 -0
  412. package/lib/swipl/library/ext/sgml/xsdp_types.pl +232 -0
  413. package/lib/swipl/library/ext/ssl/INDEX.pl +60 -0
  414. package/lib/swipl/library/ext/ssl/crypto.pl +1015 -0
  415. package/lib/swipl/library/ext/ssl/http/INDEX.pl +5 -0
  416. package/lib/swipl/library/ext/ssl/http/http_ssl_plugin.pl +296 -0
  417. package/lib/swipl/library/ext/ssl/saml.pl +609 -0
  418. package/lib/swipl/library/ext/ssl/ssl.pl +647 -0
  419. package/lib/swipl/library/ext/ssl/xmldsig.pl +391 -0
  420. package/lib/swipl/library/ext/ssl/xmlenc.pl +354 -0
  421. package/lib/swipl/library/ext/zlib/INDEX.pl +8 -0
  422. package/lib/swipl/library/ext/zlib/zlib.pl +112 -0
  423. package/lib/swipl/library/fastrw.pl +105 -0
  424. package/lib/swipl/library/files.pl +80 -0
  425. package/lib/swipl/library/gensym.pl +111 -0
  426. package/lib/swipl/library/git.pl +1027 -0
  427. package/lib/swipl/library/hashtable.pl +365 -0
  428. package/lib/swipl/library/heaps.pl +252 -0
  429. package/lib/swipl/library/hotfix.pl +239 -0
  430. package/lib/swipl/library/http/jquery.pl +103 -0
  431. package/lib/swipl/library/http/web/js/jquery-3.6.0.min.js +2 -0
  432. package/lib/swipl/library/increval.pl +217 -0
  433. package/lib/swipl/library/intercept.pl +263 -0
  434. package/lib/swipl/library/iostream.pl +237 -0
  435. package/lib/swipl/library/iri_scheme/file.pl +70 -0
  436. package/lib/swipl/library/lazy_lists.pl +481 -0
  437. package/lib/swipl/library/listing.pl +1362 -0
  438. package/lib/swipl/library/lists.pl +860 -0
  439. package/lib/swipl/library/lynx/INDEX.pl +14 -0
  440. package/lib/swipl/library/lynx/format.pl +380 -0
  441. package/lib/swipl/library/lynx/html_style.pl +129 -0
  442. package/lib/swipl/library/lynx/html_text.pl +865 -0
  443. package/lib/swipl/library/lynx/pldoc_style.pl +87 -0
  444. package/lib/swipl/library/macros.pl +451 -0
  445. package/lib/swipl/library/main.pl +1200 -0
  446. package/lib/swipl/library/make.pl +197 -0
  447. package/lib/swipl/library/modules.pl +129 -0
  448. package/lib/swipl/library/nb_rbtrees.pl +267 -0
  449. package/lib/swipl/library/nb_set.pl +203 -0
  450. package/lib/swipl/library/obfuscate.pl +115 -0
  451. package/lib/swipl/library/occurs.pl +241 -0
  452. package/lib/swipl/library/operators.pl +182 -0
  453. package/lib/swipl/library/option.pl +388 -0
  454. package/lib/swipl/library/optparse.pl +966 -0
  455. package/lib/swipl/library/ordsets.pl +518 -0
  456. package/lib/swipl/library/oset.pl +160 -0
  457. package/lib/swipl/library/pairs.pl +187 -0
  458. package/lib/swipl/library/persistency.pl +713 -0
  459. package/lib/swipl/library/pio.pl +47 -0
  460. package/lib/swipl/library/portray_text.pl +277 -0
  461. package/lib/swipl/library/pprint.pl +940 -0
  462. package/lib/swipl/library/predicate_options.pl +975 -0
  463. package/lib/swipl/library/prolog_autoload.pl +233 -0
  464. package/lib/swipl/library/prolog_breakpoints.pl +396 -0
  465. package/lib/swipl/library/prolog_clause.pl +1104 -0
  466. package/lib/swipl/library/prolog_code.pl +416 -0
  467. package/lib/swipl/library/prolog_codewalk.pl +1248 -0
  468. package/lib/swipl/library/prolog_colour.pl +3301 -0
  469. package/lib/swipl/library/prolog_colour.qlf +0 -0
  470. package/lib/swipl/library/prolog_config.pl +154 -0
  471. package/lib/swipl/library/prolog_coverage.pl +1333 -0
  472. package/lib/swipl/library/prolog_debug.pl +404 -0
  473. package/lib/swipl/library/prolog_deps.pl +675 -0
  474. package/lib/swipl/library/prolog_evaluable.pl +234 -0
  475. package/lib/swipl/library/prolog_format.pl +219 -0
  476. package/lib/swipl/library/prolog_history.pl +161 -0
  477. package/lib/swipl/library/prolog_jiti.pl +333 -0
  478. package/lib/swipl/library/prolog_locale.pl +61 -0
  479. package/lib/swipl/library/prolog_metainference.pl +307 -0
  480. package/lib/swipl/library/prolog_pack.pl +3906 -0
  481. package/lib/swipl/library/prolog_profile.pl +346 -0
  482. package/lib/swipl/library/prolog_qlfmake.pl +533 -0
  483. package/lib/swipl/library/prolog_source.pl +1188 -0
  484. package/lib/swipl/library/prolog_stack.pl +794 -0
  485. package/lib/swipl/library/prolog_trace.pl +365 -0
  486. package/lib/swipl/library/prolog_versions.pl +347 -0
  487. package/lib/swipl/library/prolog_wrap.pl +164 -0
  488. package/lib/swipl/library/prolog_xref.pl +3090 -0
  489. package/lib/swipl/library/prolog_xref.qlf +0 -0
  490. package/lib/swipl/library/pure_input.pl +266 -0
  491. package/lib/swipl/library/qpforeign.pl +695 -0
  492. package/lib/swipl/library/qsave.pl +1516 -0
  493. package/lib/swipl/library/quasi_quotations.pl +300 -0
  494. package/lib/swipl/library/quintus.pl +437 -0
  495. package/lib/swipl/library/random.pl +459 -0
  496. package/lib/swipl/library/rbtrees.pl +1153 -0
  497. package/lib/swipl/library/readln.pl +256 -0
  498. package/lib/swipl/library/readutil.pl +304 -0
  499. package/lib/swipl/library/record.pl +544 -0
  500. package/lib/swipl/library/rwlocks.pl +172 -0
  501. package/lib/swipl/library/sandbox.pl +1384 -0
  502. package/lib/swipl/library/semweb/dc.rdfs +198 -0
  503. package/lib/swipl/library/semweb/eor.rdfs +95 -0
  504. package/lib/swipl/library/semweb/owl.owl +287 -0
  505. package/lib/swipl/library/semweb/rdf_library.ttl +90 -0
  506. package/lib/swipl/library/semweb/rdfs.rdfs +251 -0
  507. package/lib/swipl/library/settings.pl +755 -0
  508. package/lib/swipl/library/shell.pl +462 -0
  509. package/lib/swipl/library/shlib.pl +670 -0
  510. package/lib/swipl/library/solution_sequences.pl +439 -0
  511. package/lib/swipl/library/sort.pl +119 -0
  512. package/lib/swipl/library/statistics.pl +541 -0
  513. package/lib/swipl/library/streams.pl +118 -0
  514. package/lib/swipl/library/strings.pl +469 -0
  515. package/lib/swipl/library/system.pl +95 -0
  516. package/lib/swipl/library/tables.pl +381 -0
  517. package/lib/swipl/library/tableutil.pl +771 -0
  518. package/lib/swipl/library/tabling.pl +42 -0
  519. package/lib/swipl/library/terms.pl +457 -0
  520. package/lib/swipl/library/theme/auto.pl +61 -0
  521. package/lib/swipl/library/theme/dark.pl +455 -0
  522. package/lib/swipl/library/theme/light.pl +45 -0
  523. package/lib/swipl/library/thread.pl +810 -0
  524. package/lib/swipl/library/thread_pool.pl +508 -0
  525. package/lib/swipl/library/threadutil.pl +574 -0
  526. package/lib/swipl/library/tty.pl +316 -0
  527. package/lib/swipl/library/ugraphs.pl +644 -0
  528. package/lib/swipl/library/unicode/INDEX.pl +6 -0
  529. package/lib/swipl/library/unicode/blocks.pl +414 -0
  530. package/lib/swipl/library/url.pl +1129 -0
  531. package/lib/swipl/library/utf8.pl +145 -0
  532. package/lib/swipl/library/varnumbers.pl +221 -0
  533. package/lib/swipl/library/vm.pl +251 -0
  534. package/lib/swipl/library/wfs.pl +205 -0
  535. package/lib/swipl/library/when.pl +263 -0
  536. package/lib/swipl/library/writef.pl +278 -0
  537. package/lib/swipl/library/www_browser.pl +251 -0
  538. package/lib/swipl/library/yall.pl +574 -0
  539. package/lib/swipl/library/zip.pl +211 -0
  540. package/lib/swipl/swipl.home +1 -0
  541. package/lib/vendor/libcrypto.so.3 +0 -0
  542. package/lib/vendor/libpcre2-8.so.0 +0 -0
  543. package/lib/vendor/libssl.so.3 +0 -0
  544. package/lib/vendor/libz.so.1 +0 -0
  545. package/licenses/OpenSSL-LICENSE.txt +177 -0
  546. package/licenses/PCRE2-COPYING +5 -0
  547. package/licenses/README.md +12 -0
  548. package/licenses/SWI-Prolog-LICENSE +41 -0
  549. package/licenses/zlib-LICENSE +22 -0
  550. package/package.json +27 -0
@@ -0,0 +1,810 @@
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) 2007-2025, University of Amsterdam
7
+ VU University Amsterdam
8
+ CWI, Amsterdam
9
+ SWI-Prolog Solutions b.v.
10
+ All rights reserved.
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions
14
+ are met:
15
+
16
+ 1. Redistributions of source code must retain the above copyright
17
+ notice, this list of conditions and the following disclaimer.
18
+
19
+ 2. Redistributions in binary form must reproduce the above copyright
20
+ notice, this list of conditions and the following disclaimer in
21
+ the documentation and/or other materials provided with the
22
+ distribution.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
+ POSSIBILITY OF SUCH DAMAGE.
36
+ */
37
+
38
+ :- module(thread,
39
+ [ concurrent/3, % +Threads, :Goals, +Options
40
+ concurrent_maplist/2, % :Goal, +List
41
+ concurrent_maplist/3, % :Goal, ?List1, ?List2
42
+ concurrent_maplist/4, % :Goal, ?List1, ?List2, ?List3
43
+ concurrent_forall/2, % :Generate, :Test
44
+ concurrent_forall/3, % :Generate, :Test, +Options
45
+ concurrent_and/2, % :Generator,:Test
46
+ concurrent_and/3, % :Generator,:Test,+Options
47
+ first_solution/3, % -Var, :Goals, +Options
48
+
49
+ call_in_thread/2, % +Thread, :Goal
50
+ call_in_thread/3 % +Thread, :Goal, +Options
51
+ ]).
52
+ :- autoload(library(apply), [maplist/2, maplist/3, maplist/4, maplist/5]).
53
+ :- autoload(library(error), [must_be/2, instantiation_error/1]).
54
+ :- autoload(library(lists), [subtract/3, same_length/2, nth0/3]).
55
+ :- autoload(library(option), [option/2, option/3, meta_options/3]).
56
+ :- autoload(library(ordsets), [ord_intersection/3, ord_union/3]).
57
+ :- use_module(library(debug), [debug/3, assertion/1]).
58
+
59
+ %:- debug(concurrent).
60
+
61
+ :- meta_predicate
62
+ concurrent(+, :, +),
63
+ concurrent_maplist(1, +),
64
+ concurrent_maplist(2, ?, ?),
65
+ concurrent_maplist(3, ?, ?, ?),
66
+ concurrent_forall(0, 0),
67
+ concurrent_forall(0, 0, +),
68
+ concurrent_and(0, 0),
69
+ concurrent_and(0, 0, +),
70
+ first_solution(-, :, +),
71
+ call_in_thread(+, 0),
72
+ call_in_thread(+, 0, :).
73
+
74
+
75
+ :- predicate_options(concurrent/3, 3,
76
+ [ pass_to(system:thread_create/3, 3)
77
+ ]).
78
+ :- predicate_options(concurrent_forall/3, 3,
79
+ [ threads(nonneg)
80
+ ]).
81
+ :- predicate_options(concurrent_and/3, 3,
82
+ [ threads(nonneg)
83
+ ]).
84
+ :- predicate_options(first_solution/3, 3,
85
+ [ on_fail(oneof([stop,continue])),
86
+ on_error(oneof([stop,continue])),
87
+ pass_to(system:thread_create/3, 3)
88
+ ]).
89
+
90
+ /** <module> High level thread primitives
91
+
92
+ This module defines simple to use predicates for running goals
93
+ concurrently. Where the core multi-threaded API is targeted at
94
+ communicating long-living threads, the predicates here are defined to
95
+ run goals concurrently without having to deal with thread creation and
96
+ maintenance explicitely.
97
+
98
+ Note that these predicates run goals concurrently and therefore these
99
+ goals need to be thread-safe. As the predicates in this module also
100
+ abort branches of the computation that are no longer needed, predicates
101
+ that have side-effect must act properly. In a nutshell, this has the
102
+ following consequences:
103
+
104
+ * Nice clean Prolog code without side-effects (but with cut) works
105
+ fine.
106
+ * Side-effects are bad news. If you really need assert to store
107
+ intermediate results, use the thread_local/1 declaration. This
108
+ also guarantees cleanup of left-over clauses if the thread is
109
+ cancelled. For other side-effects, make sure to use call_cleanup/2
110
+ to undo them should the thread be cancelled.
111
+ * Global variables are ok as they are thread-local and destroyed
112
+ on thread cancellation. Note however that global variables in
113
+ the calling thread are *not* available in the threads that are
114
+ created. You have to pass the value as an argument and initialise
115
+ the variable in the new thread.
116
+ * Thread-cancellation uses thread_signal/2. Using this code
117
+ with long-blocking foreign predicates may result in long delays,
118
+ even if another thread asks for cancellation.
119
+
120
+ @author Jan Wielemaker
121
+ */
122
+
123
+ %! concurrent(+N, :Goals, +Options) is semidet.
124
+ %
125
+ % Run Goals in parallel using N threads. This call blocks until
126
+ % all work has been done. The Goals must be independent. They
127
+ % should not communicate using shared variables or any form of
128
+ % global data. All Goals must be thread-safe.
129
+ %
130
+ % Execution succeeds if all goals have succeeded. If one goal
131
+ % fails or throws an exception, other workers are abandoned as
132
+ % soon as possible and the entire computation fails or re-throws
133
+ % the exception. Note that if multiple goals fail or raise an
134
+ % error it is not defined which error or failure is reported.
135
+ %
136
+ % On successful completion, variable bindings are returned. Note
137
+ % however that threads have independent stacks and therefore the
138
+ % goal is copied to the worker thread and the result is copied
139
+ % back to the caller of concurrent/3.
140
+ %
141
+ % Choosing the right number of threads is not always obvious. Here
142
+ % are some scenarios:
143
+ %
144
+ % * If the goals are CPU intensive and normally all succeeding,
145
+ % typically the number of CPUs is the optimal number of
146
+ % threads. Less does not use all CPUs, more wastes time in
147
+ % context switches and also uses more memory.
148
+ %
149
+ % * If the tasks are I/O bound the number of threads is
150
+ % typically higher than the number of CPUs.
151
+ %
152
+ % * If one or more of the goals may fail or produce an error,
153
+ % using a higher number of threads may find this earlier.
154
+ %
155
+ % @arg N Number of worker-threads to create. Using 1, no threads
156
+ % are created. If N is larger than the number of Goals we
157
+ % create exactly as many threads as there are Goals.
158
+ % @arg Goals List of callable terms.
159
+ % @arg Options Passed to thread_create/3 for creating the
160
+ % workers. Only options changing the stack-sizes can
161
+ % be used. In particular, do not pass the detached or alias
162
+ % options.
163
+ % @see In many cases, concurrent_maplist/2 and friends
164
+ % is easier to program and is tractable to program
165
+ % analysis.
166
+
167
+ concurrent(1, M:List, _) :-
168
+ !,
169
+ maplist(once_in_module(M), List).
170
+ concurrent(N, M:List, Options) :-
171
+ must_be(positive_integer, N),
172
+ must_be(list(callable), List),
173
+ length(List, JobCount),
174
+ message_queue_create(Done),
175
+ message_queue_create(Queue),
176
+ WorkerCount is min(N, JobCount),
177
+ create_workers(WorkerCount, Queue, Done, Workers, Options),
178
+ submit_goals(List, 1, M, Queue, VarList),
179
+ forall(between(1, WorkerCount, _),
180
+ thread_send_message(Queue, done)),
181
+ VT =.. [vars|VarList],
182
+ concur_wait(JobCount, Done, VT, cleanup(Workers, Queue),
183
+ Result, [], Exitted),
184
+ subtract(Workers, Exitted, RemainingWorkers),
185
+ concur_cleanup(Result, RemainingWorkers, [Queue, Done]),
186
+ ( Result == true
187
+ -> true
188
+ ; Result = false
189
+ -> fail
190
+ ; Result = exception(Error)
191
+ -> throw(Error)
192
+ ).
193
+
194
+ once_in_module(M, Goal) :-
195
+ call(M:Goal), !.
196
+
197
+ %! submit_goals(+List, +Id0, +Module, +Queue, -Vars) is det.
198
+ %
199
+ % Send all jobs from List to Queue. Each goal is added to Queue as
200
+ % a term goal(Id, Goal, Vars). Vars is unified with a list of
201
+ % lists of free variables appearing in each goal.
202
+
203
+ submit_goals([], _, _, _, []).
204
+ submit_goals([H|T], I, M, Queue, [Vars|VT]) :-
205
+ term_variables(H, Vars),
206
+ thread_send_message(Queue, goal(I, M:H, Vars)),
207
+ I2 is I + 1,
208
+ submit_goals(T, I2, M, Queue, VT).
209
+
210
+
211
+ %! concur_wait(+N, +Done:queue, +VT:compound, +Cleanup,
212
+ %! -Result, +Exitted0, -Exitted) is semidet.
213
+ %
214
+ % Wait for completion, failure or error.
215
+ %
216
+ % @arg Exited List of thread-ids with threads that completed
217
+ % before all work was done.
218
+
219
+ concur_wait(0, _, _, _, true, Exited, Exited) :- !.
220
+ concur_wait(N, Done, VT, Cleanup, Status, Exitted0, Exitted) :-
221
+ debug(concurrent, 'Concurrent: waiting for workers ...', []),
222
+ catch(thread_get_message(Done, Exit), Error,
223
+ concur_abort(Error, Cleanup, Done, Exitted0)),
224
+ debug(concurrent, 'Waiting: received ~p', [Exit]),
225
+ ( Exit = done(Id, Vars)
226
+ -> debug(concurrent, 'Concurrent: Job ~p completed with ~p', [Id, Vars]),
227
+ arg(Id, VT, Vars),
228
+ N2 is N - 1,
229
+ concur_wait(N2, Done, VT, Cleanup, Status, Exitted0, Exitted)
230
+ ; Exit = finished(Thread)
231
+ -> thread_join(Thread, JoinStatus),
232
+ debug(concurrent, 'Concurrent: waiter ~p joined: ~p',
233
+ [Thread, JoinStatus]),
234
+ ( JoinStatus == true
235
+ -> concur_wait(N, Done, VT, Cleanup, Status, [Thread|Exitted0], Exitted)
236
+ ; Status = JoinStatus,
237
+ Exitted = [Thread|Exitted0]
238
+ )
239
+ ).
240
+
241
+ concur_abort(Error, cleanup(Workers, Queue), Done, Exitted) :-
242
+ debug(concurrent, 'Concurrent: got ~p', [Error]),
243
+ subtract(Workers, Exitted, RemainingWorkers),
244
+ concur_cleanup(Error, RemainingWorkers, [Queue, Done]),
245
+ throw(Error).
246
+
247
+ create_workers(N, Queue, Done, [Id|Ids], Options) :-
248
+ N > 0,
249
+ !,
250
+ thread_create(worker(Queue, Done), Id,
251
+ [ at_exit(thread_send_message(Done, finished(Id)))
252
+ | Options
253
+ ]),
254
+ N2 is N - 1,
255
+ create_workers(N2, Queue, Done, Ids, Options).
256
+ create_workers(_, _, _, [], _).
257
+
258
+
259
+ %! worker(+WorkQueue, +DoneQueue) is det.
260
+ %
261
+ % Process jobs from WorkQueue and send the results to DoneQueue.
262
+
263
+ worker(Queue, Done) :-
264
+ thread_get_message(Queue, Message),
265
+ debug(concurrent, 'Worker: received ~p', [Message]),
266
+ ( Message = goal(Id, Goal, Vars)
267
+ -> ( Goal
268
+ -> thread_send_message(Done, done(Id, Vars)),
269
+ worker(Queue, Done)
270
+ )
271
+ ; true
272
+ ).
273
+
274
+
275
+ %! concur_cleanup(+Result, +Workers:list, +Queues:list) is det.
276
+ %
277
+ % Cleanup the concurrent workers and message queues. If Result is
278
+ % not =true=, signal all workers to make them stop prematurely. If
279
+ % result is true we assume all workers have been instructed to
280
+ % stop or have stopped themselves.
281
+
282
+ concur_cleanup(Result, Workers, Queues) :-
283
+ !,
284
+ ( Result == true
285
+ -> true
286
+ ; kill_workers(Workers)
287
+ ),
288
+ join_all(Workers),
289
+ maplist(message_queue_destroy, Queues).
290
+
291
+ kill_workers([]).
292
+ kill_workers([Id|T]) :-
293
+ debug(concurrent, 'Signalling ~w', [Id]),
294
+ catch(thread_signal(Id, abort), _, true),
295
+ kill_workers(T).
296
+
297
+ join_all([]).
298
+ join_all([Id|T]) :-
299
+ thread_join(Id, _),
300
+ join_all(T).
301
+
302
+
303
+ /*******************************
304
+ * FORALL *
305
+ *******************************/
306
+
307
+ %! concurrent_forall(:Generate, :Action) is semidet.
308
+ %! concurrent_forall(:Generate, :Action, +Options) is semidet.
309
+ %
310
+ % True when Action is true for all solutions of Generate. This has the
311
+ % same semantics as forall/2, but the Action goals are executed in
312
+ % multiple threads. Notable a failing Action or a Action throwing an
313
+ % exception signals the calling thread which in turn aborts all
314
+ % workers and fails or re-throws the generated error. Options:
315
+ %
316
+ % - threads(+Count)
317
+ % Number of threads to use. The default is determined by the
318
+ % Prolog flag `cpu_count`.
319
+ %
320
+ % @tbd Ideally we would grow the set of workers dynamically, similar
321
+ % to dynamic scheduling of HTTP worker threads. This would avoid
322
+ % creating threads that are never used if Generate is too slow or does
323
+ % not provide enough answers and would further raise the number of
324
+ % threads if Action is I/O bound rather than CPU bound.
325
+
326
+ :- dynamic
327
+ fa_aborted/1.
328
+
329
+ concurrent_forall(Generate, Test) :-
330
+ concurrent_forall(Generate, Test, []).
331
+
332
+ concurrent_forall(Generate, Test, Options) :-
333
+ jobs(Jobs, Options),
334
+ Jobs > 1,
335
+ !,
336
+ term_variables(Generate, GVars),
337
+ term_variables(Test, TVars),
338
+ sort(GVars, GVarsS),
339
+ sort(TVars, TVarsS),
340
+ ord_intersection(GVarsS, TVarsS, Shared),
341
+ Templ =.. [v|Shared],
342
+ MaxSize is Jobs*4,
343
+ message_queue_create(Q, [max_size(MaxSize)]),
344
+ length(Workers, Jobs),
345
+ thread_self(Me),
346
+ maplist(thread_create(fa_worker(Q, Me, Templ, Test)), Workers),
347
+ catch(( forall(Generate,
348
+ thread_send_message(Q, job(Templ))),
349
+ forall(between(1, Jobs, _),
350
+ thread_send_message(Q, done)),
351
+ maplist(thread_join, Workers),
352
+ message_queue_destroy(Q)
353
+ ),
354
+ Error,
355
+ fa_cleanup(Error, Workers, Q)).
356
+ concurrent_forall(Generate, Test, _) :-
357
+ forall(Generate, Test).
358
+
359
+ fa_cleanup(Error, Workers, Q) :-
360
+ maplist(safe_abort, Workers),
361
+ debug(concurrent(fail), 'Joining workers', []),
362
+ maplist(safe_join, Workers),
363
+ debug(concurrent(fail), 'Destroying queue', []),
364
+ retractall(fa_aborted(Q)),
365
+ message_queue_destroy(Q),
366
+ ( Error = fa_worker_failed(_0Test, Why)
367
+ -> debug(concurrent(fail), 'Test ~p failed: ~p', [_0Test, Why]),
368
+ ( Why == false
369
+ -> fail
370
+ ; Why = error(E)
371
+ -> throw(E)
372
+ ; assertion(fail)
373
+ )
374
+ ; throw(Error)
375
+ ).
376
+
377
+ fa_worker(Queue, Main, Templ, Test) :-
378
+ repeat,
379
+ thread_get_message(Queue, Msg),
380
+ ( Msg == done
381
+ -> !
382
+ ; Msg = job(Templ),
383
+ debug(concurrent, 'Running test ~p', [Test]),
384
+ ( catch_with_backtrace(Test, E, true)
385
+ -> ( var(E)
386
+ -> fail
387
+ ; fa_stop(Queue, Main, fa_worker_failed(Test, error(E)))
388
+ )
389
+ ; !,
390
+ fa_stop(Queue, Main, fa_worker_failed(Test, false))
391
+ )
392
+ ).
393
+
394
+ fa_stop(Queue, Main, Why) :-
395
+ with_mutex('$concurrent_forall',
396
+ fa_stop_sync(Queue, Main, Why)).
397
+
398
+ fa_stop_sync(Queue, _Main, _Why) :-
399
+ fa_aborted(Queue),
400
+ !.
401
+ fa_stop_sync(Queue, Main, Why) :-
402
+ asserta(fa_aborted(Queue)),
403
+ debug(concurrent(fail), 'Stop due to ~p. Signalling ~q', [Why, Main]),
404
+ thread_signal(Main, throw(Why)).
405
+
406
+ jobs(Jobs, Options) :-
407
+ ( option(threads(Jobs), Options)
408
+ -> true
409
+ ; current_prolog_flag(cpu_count, Jobs)
410
+ -> true
411
+ ; Jobs = 1
412
+ ).
413
+
414
+ safe_abort(Thread) :-
415
+ catch(thread_signal(Thread, abort), error(_,_), true).
416
+ safe_join(Thread) :-
417
+ E = error(_,_),
418
+ catch(thread_join(Thread, _Status), E, true).
419
+
420
+
421
+ /*******************************
422
+ * AND *
423
+ *******************************/
424
+
425
+ %! concurrent_and(:Generator, :Test).
426
+ %! concurrent_and(:Generator, :Test, +Options).
427
+ %
428
+ % Concurrent version of `(Generator,Test)`. This predicate creates a
429
+ % thread providing solutions for Generator that are handed to a pool
430
+ % of threads that run Test for the different instantiations provided
431
+ % by Generator concurrently. The predicate is logically equivalent to
432
+ % a simple conjunction except for two aspects: (1) terms are _copied_
433
+ % from Generator to the test Test threads while answers are copied
434
+ % back to the calling thread and (2) answers may be produced out of
435
+ % order.
436
+ %
437
+ % If the evaluation of some Test raises an exception,
438
+ % concurrent_and/2,3 is terminated with this exception. If the caller
439
+ % commits after a given answer or raises an exception while
440
+ % concurrent_and/2,3 is active with pending choice points, all
441
+ % involved resources are reclaimed.
442
+ %
443
+ % Options:
444
+ %
445
+ % - threads(+Count)
446
+ % Create a worker pool holding Count threads. The default is
447
+ % the Prolog flag `cpu_count`.
448
+ %
449
+ % This predicate was proposed by Jan Burse as
450
+ % balance((Generator,Test)).
451
+
452
+ concurrent_and(Gen, Test) :-
453
+ concurrent_and(Gen, Test, []).
454
+
455
+ concurrent_and(Gen, Test, Options) :-
456
+ jobs(Jobs, Options),
457
+ MaxSize is Jobs*4,
458
+ message_queue_create(JobQueue, [max_size(MaxSize)]),
459
+ message_queue_create(AnswerQueue, [max_size(MaxSize)]),
460
+ ca_template(Gen, Test, Templ),
461
+ term_variables(Gen+Test, AllVars),
462
+ ReplyTempl =.. [v|AllVars],
463
+ length(Workers, Jobs),
464
+ Alive is 1<<Jobs-1,
465
+ maplist(thread_create(ca_worker(JobQueue, AnswerQueue,
466
+ Templ, Test, ReplyTempl)),
467
+ Workers),
468
+ thread_create(ca_generator(Gen, Templ, JobQueue, AnswerQueue),
469
+ GenThread),
470
+ State = state(Alive),
471
+ call_cleanup(
472
+ ca_gather(State, AnswerQueue, ReplyTempl, Workers),
473
+ ca_cleanup(GenThread, Workers, JobQueue, AnswerQueue)).
474
+
475
+ ca_gather(State, AnswerQueue, ReplyTempl, Workers) :-
476
+ repeat,
477
+ thread_get_message(AnswerQueue, Msg),
478
+ ( Msg = true(ReplyTempl)
479
+ -> true
480
+ ; Msg = done(Worker)
481
+ -> nth0(Done, Workers, Worker),
482
+ arg(1, State, Alive0),
483
+ Alive1 is Alive0 /\ \(1<<Done),
484
+ debug(concurrent(and), 'Alive = ~2r', [Alive1]),
485
+ ( Alive1 =:= 0
486
+ -> !,
487
+ fail
488
+ ; nb_setarg(1, State, Alive1),
489
+ fail
490
+ )
491
+ ; Msg = error(E)
492
+ -> throw(E)
493
+ ).
494
+
495
+ ca_template(Gen, Test, Templ) :-
496
+ term_variables(Gen, GVars),
497
+ term_variables(Test, TVars),
498
+ sort(GVars, GVarsS),
499
+ sort(TVars, TVarsS),
500
+ ord_intersection(GVarsS, TVarsS, Shared),
501
+ ord_union(GVarsS, Shared, TemplVars),
502
+ Templ =.. [v|TemplVars].
503
+
504
+ ca_worker(JobQueue, AnswerQueue, Templ, Test, ReplyTempl) :-
505
+ thread_self(Me),
506
+ EG = error(existence_error(message_queue, _), _),
507
+ repeat,
508
+ catch(thread_get_message(JobQueue, Req), EG, Req=all_done),
509
+ ( Req = job(Templ)
510
+ -> ( catch(Test, E, true),
511
+ ( var(E)
512
+ -> thread_send_message(AnswerQueue, true(ReplyTempl))
513
+ ; thread_send_message(AnswerQueue, error(E))
514
+ ),
515
+ fail
516
+ )
517
+ ; Req == done
518
+ -> !,
519
+ message_queue_destroy(JobQueue),
520
+ thread_send_message(AnswerQueue, done(Me))
521
+ ; assertion(Req == all_done)
522
+ -> !,
523
+ thread_send_message(AnswerQueue, done(Me))
524
+ ).
525
+
526
+ ca_generator(Gen, Templ, JobQueue, AnswerQueue) :-
527
+ ( catch(Gen, E, true),
528
+ ( var(E)
529
+ -> thread_send_message(JobQueue, job(Templ))
530
+ ; thread_send_message(AnswerQueue, error(E))
531
+ ),
532
+ fail
533
+ ; thread_send_message(JobQueue, done)
534
+ ).
535
+
536
+ ca_cleanup(GenThread, Workers, JobQueue, AnswerQueue) :-
537
+ safe_abort(GenThread),
538
+ safe_join(GenThread),
539
+ maplist(safe_abort, Workers),
540
+ maplist(safe_join, Workers),
541
+ message_queue_destroy(AnswerQueue),
542
+ catch(message_queue_destroy(JobQueue), error(_,_), true).
543
+
544
+
545
+ /*******************************
546
+ * MAPLIST *
547
+ *******************************/
548
+
549
+ %! concurrent_maplist(:Goal, +List) is semidet.
550
+ %! concurrent_maplist(:Goal, +List1, +List2) is semidet.
551
+ %! concurrent_maplist(:Goal, +List1, +List2, +List3) is semidet.
552
+ %
553
+ % Concurrent version of maplist/2. This predicate uses concurrent/3,
554
+ % using multiple _worker_ threads. The number of threads is the
555
+ % minimum of the list length and the number of cores available. The
556
+ % number of cores is determined using the prolog flag =cpu_count=. If
557
+ % this flag is absent or 1 or List has less than two elements, this
558
+ % predicate calls the corresponding maplist/N version using a wrapper
559
+ % based on once/1. Note that all goals are executed as if wrapped in
560
+ % once/1 and therefore these predicates are _semidet_.
561
+ %
562
+ % Note that the the overhead of this predicate is considerable and
563
+ % therefore Goal must be fairly expensive before one reaches a
564
+ % speedup.
565
+
566
+ concurrent_maplist(Goal, List) :-
567
+ workers(List, WorkerCount),
568
+ !,
569
+ maplist(ml_goal(Goal), List, Goals),
570
+ concurrent(WorkerCount, Goals, []).
571
+ concurrent_maplist(M:Goal, List) :-
572
+ maplist(once_in_module(M, Goal), List).
573
+
574
+ once_in_module(M, Goal, Arg) :-
575
+ call(M:Goal, Arg), !.
576
+
577
+ ml_goal(Goal, Elem, call(Goal, Elem)).
578
+
579
+ concurrent_maplist(Goal, List1, List2) :-
580
+ same_length(List1, List2),
581
+ workers(List1, WorkerCount),
582
+ !,
583
+ maplist(ml_goal(Goal), List1, List2, Goals),
584
+ concurrent(WorkerCount, Goals, []).
585
+ concurrent_maplist(M:Goal, List1, List2) :-
586
+ maplist(once_in_module(M, Goal), List1, List2).
587
+
588
+ once_in_module(M, Goal, Arg1, Arg2) :-
589
+ call(M:Goal, Arg1, Arg2), !.
590
+
591
+ ml_goal(Goal, Elem1, Elem2, call(Goal, Elem1, Elem2)).
592
+
593
+ concurrent_maplist(Goal, List1, List2, List3) :-
594
+ same_length(List1, List2, List3),
595
+ workers(List1, WorkerCount),
596
+ !,
597
+ maplist(ml_goal(Goal), List1, List2, List3, Goals),
598
+ concurrent(WorkerCount, Goals, []).
599
+ concurrent_maplist(M:Goal, List1, List2, List3) :-
600
+ maplist(once_in_module(M, Goal), List1, List2, List3).
601
+
602
+ once_in_module(M, Goal, Arg1, Arg2, Arg3) :-
603
+ call(M:Goal, Arg1, Arg2, Arg3), !.
604
+
605
+ ml_goal(Goal, Elem1, Elem2, Elem3, call(Goal, Elem1, Elem2, Elem3)).
606
+
607
+ workers(List, Count) :-
608
+ current_prolog_flag(cpu_count, Cores),
609
+ Cores > 1,
610
+ length(List, Len),
611
+ Count is min(Cores,Len),
612
+ Count > 1,
613
+ !.
614
+
615
+ same_length([], [], []).
616
+ same_length([_|T1], [_|T2], [_|T3]) :-
617
+ same_length(T1, T2, T3).
618
+
619
+
620
+ /*******************************
621
+ * FIRST *
622
+ *******************************/
623
+
624
+ %! first_solution(-X, :Goals, +Options) is semidet.
625
+ %
626
+ % Try alternative solvers concurrently, returning the first
627
+ % answer. In a typical scenario, solving any of the goals in Goals
628
+ % is satisfactory for the application to continue. As soon as one
629
+ % of the tried alternatives is successful, all the others are
630
+ % killed and first_solution/3 succeeds.
631
+ %
632
+ % For example, if it is unclear whether it is better to search a
633
+ % graph breadth-first or depth-first we can use:
634
+ %
635
+ % ==
636
+ % search_graph(Grap, Path) :-
637
+ % first_solution(Path, [ breadth_first(Graph, Path),
638
+ % depth_first(Graph, Path)
639
+ % ],
640
+ % []).
641
+ % ==
642
+ %
643
+ % Options include thread stack-sizes passed to thread_create, as
644
+ % well as the options =on_fail= and =on_error= that specify what
645
+ % to do if a solver fails or triggers an error. By default
646
+ % execution of all solvers is terminated and the result is
647
+ % returned. Sometimes one may wish to continue. One such scenario
648
+ % is if one of the solvers may run out of resources or one of the
649
+ % solvers is known to be incomplete.
650
+ %
651
+ % * on_fail(Action)
652
+ % If =stop= (default), terminate all threads and stop with
653
+ % the failure. If =continue=, keep waiting.
654
+ % * on_error(Action)
655
+ % As above, re-throwing the error if an error appears.
656
+ %
657
+ % @bug first_solution/3 cannot deal with non-determinism. There
658
+ % is no obvious way to fit non-determinism into it. If multiple
659
+ % solutions are needed wrap the solvers in findall/3.
660
+
661
+
662
+ first_solution(X, M:List, Options) :-
663
+ message_queue_create(Done),
664
+ thread_options(Options, ThreadOptions, RestOptions),
665
+ length(List, JobCount),
666
+ create_solvers(List, M, X, Done, Solvers, ThreadOptions),
667
+ wait_for_one(JobCount, Done, Result, RestOptions),
668
+ concur_cleanup(kill, Solvers, [Done]),
669
+ ( Result = done(_, Var)
670
+ -> X = Var
671
+ ; Result = error(_, Error)
672
+ -> throw(Error)
673
+ ).
674
+
675
+ create_solvers([], _, _, _, [], _).
676
+ create_solvers([H|T], M, X, Done, [Id|IDs], Options) :-
677
+ thread_create(solve(M:H, X, Done), Id, Options),
678
+ create_solvers(T, M, X, Done, IDs, Options).
679
+
680
+ solve(Goal, Var, Queue) :-
681
+ thread_self(Me),
682
+ ( catch(Goal, E, true)
683
+ -> ( var(E)
684
+ -> thread_send_message(Queue, done(Me, Var))
685
+ ; thread_send_message(Queue, error(Me, E))
686
+ )
687
+ ; thread_send_message(Queue, failed(Me))
688
+ ).
689
+
690
+ wait_for_one(0, _, failed, _) :- !.
691
+ wait_for_one(JobCount, Queue, Result, Options) :-
692
+ thread_get_message(Queue, Msg),
693
+ LeftCount is JobCount - 1,
694
+ ( Msg = done(_, _)
695
+ -> Result = Msg
696
+ ; Msg = failed(_)
697
+ -> ( option(on_fail(stop), Options, stop)
698
+ -> Result = Msg
699
+ ; wait_for_one(LeftCount, Queue, Result, Options)
700
+ )
701
+ ; Msg = error(_, _)
702
+ -> ( option(on_error(stop), Options, stop)
703
+ -> Result = Msg
704
+ ; wait_for_one(LeftCount, Queue, Result, Options)
705
+ )
706
+ ).
707
+
708
+
709
+ %! thread_options(+Options, -ThreadOptions, -RestOptions) is det.
710
+ %
711
+ % Split the option list over thread(-size) options and other
712
+ % options.
713
+
714
+ thread_options([], [], []).
715
+ thread_options([H|T], [H|Th], O) :-
716
+ thread_option(H),
717
+ !,
718
+ thread_options(T, Th, O).
719
+ thread_options([H|T], Th, [H|O]) :-
720
+ thread_options(T, Th, O).
721
+
722
+ thread_option(local(_)).
723
+ thread_option(global(_)).
724
+ thread_option(trail(_)).
725
+ thread_option(argument(_)).
726
+ thread_option(stack(_)).
727
+
728
+
729
+ %! call_in_thread(+Thread, :Goal) is semidet.
730
+ %! call_in_thread(+Thread, :Goal, +Options) is semidet.
731
+ %
732
+ % Run Goal as an interrupt in the context of Thread. This is based on
733
+ % thread_signal/2. If waiting times out, we inject a stop(Reason)
734
+ % exception into Goal. Interrupts can be nested, i.e., it is allowed
735
+ % to run a call_in_thread/2 while the target thread is processing such
736
+ % an interrupt.
737
+ %
738
+ % Options are passed to thread_get_message/3 and notably allow for
739
+ % specifying a timeout. If a timeout is reached, this predicate will
740
+ % attempt to kill Goal in Thread and act according to the option
741
+ % `on_timeout`.
742
+ %
743
+ % - on_timeout(:Goal)
744
+ % If waiting terminates due to a timeout(Time), or deadline(Stamp)
745
+ % option, call Goal. The default is throw(time_limit_exceeded).
746
+ %
747
+ % This predicate is primarily intended for debugging and inspection
748
+ % tasks.
749
+
750
+ call_in_thread(Thread, Goal) :-
751
+ call_in_thread(Thread, Goal, []).
752
+
753
+ call_in_thread(Thread, Goal, _) :-
754
+ must_be(callable, Goal),
755
+ var(Thread),
756
+ !,
757
+ instantiation_error(Thread).
758
+ call_in_thread(Thread, Goal, _) :-
759
+ thread_self(Thread),
760
+ !,
761
+ once(Goal).
762
+ call_in_thread(Thread, Goal, Options) :-
763
+ meta_options(is_meta, Options, Options1),
764
+ term_variables(Goal, Vars),
765
+ thread_self(Me),
766
+ A is random(1 000 000 000),
767
+ thread_signal(Thread, run_in_thread(Goal,Vars,A,Me)),
768
+ ( catch(thread_get_message(Me, in_thread(A,Result), Options1),
769
+ Error,
770
+ forward_exception(Thread, A, Error))
771
+ -> ( Result = true(Vars)
772
+ -> true
773
+ ; Result = error(Error)
774
+ -> throw(Error)
775
+ ; fail
776
+ )
777
+ ; thread_signal(Thread, kill_task(A, stop(time_limit_exceeded))),
778
+ option(on_timeout(Action), Options1, throw(time_limit_exceeded)),
779
+ call(Action)
780
+ ).
781
+
782
+ is_meta(on_timeout).
783
+
784
+ run_in_thread(Goal, Vars, Id, Sender) :-
785
+ ( catch_with_backtrace(call(Goal), Error, true)
786
+ -> ( var(Error)
787
+ -> thread_send_message(Sender, in_thread(Id, true(Vars)))
788
+ ; Error = stop(_)
789
+ -> true
790
+ ; thread_send_message(Sender, in_thread(Id, error(Error)))
791
+ )
792
+ ; thread_send_message(Sender, in_thread(Id, false))
793
+ ).
794
+
795
+ forward_exception(Thread, Id, Error) :-
796
+ kill_with(Error, Kill),
797
+ thread_signal(Thread, kill_task(Id, Kill)),
798
+ throw(Error).
799
+
800
+ kill_with(time_limit_exceeded, stop(time_limit_exceeded)) :-
801
+ !.
802
+ kill_with(_, stop(interrupt)).
803
+
804
+ kill_task(Id, Exception) :-
805
+ prolog_current_frame(Frame),
806
+ prolog_frame_attribute(Frame, parent_goal,
807
+ run_in_thread(_Goal, _Vars, Id, _Sender)),
808
+ !,
809
+ throw(Exception).
810
+ kill_task(_, _).