View source with formatted comments or as raw
   1/*  Part of XPCE --- The SWI-Prolog GUI toolkit
   2
   3    Author:        Jan Wielemaker and Anjo Anjewierden
   4    E-mail:        J.Wielemaker@cs.vu.nl
   5    WWW:           http://www.swi-prolog.org/packages/xpce/
   6    Copyright (c)  2009-2015, University of Amsterdam
   7                              VU University Amsterdam
   8    All rights reserved.
   9
  10    Redistribution and use in source and binary forms, with or without
  11    modification, are permitted provided that the following conditions
  12    are met:
  13
  14    1. Redistributions of source code must retain the above copyright
  15       notice, this list of conditions and the following disclaimer.
  16
  17    2. Redistributions in binary form must reproduce the above copyright
  18       notice, this list of conditions and the following disclaimer in
  19       the documentation and/or other materials provided with the
  20       distribution.
  21
  22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  30    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33    POSSIBILITY OF SUCH DAMAGE.
  34*/
  35
  36:- module(pce_dispatch,
  37          [ pce_dispatch/1,             % +Options
  38            pce_end_dispatch/0,
  39            pce_call/1                  % :Goal
  40          ]).
  41:- use_module(library(pce)).
  42
  43:- meta_predicate
  44    pce_call(0).
  45
  46/** <module> Run XPCE in a separate thread
  47
  48This module allows one to run XPCE in   a separate thread =pce=. This is
  49especially  nice  if  xpce  is  only  used  to  support  the  SWI-Prolog
  50development tools because it ensures that   the  tools remain responsive
  51while the main thread executes long-running goals.
  52
  53This module can be deactivated by setting the flag `xpce_threaded`:
  54
  55  ==
  56  :- set_prolog_flag(xpce_threaded, false).
  57  ==
  58*/
  59
  60:- predicate_options(pce_dispatch/1, 1,
  61                     [ pass_to(system:thread_create/3, 3)
  62                     ]).
  63
  64%!  pce_dispatch(+Options) is det.
  65%
  66%   Create a new thread =pce= that takes   care  of the XPCE message
  67%   loop. This predicate has no effect  if dispatching is already on
  68%   another thread than the =main=.  The   loop  can  be ended using
  69%   pce_end_dispatch/0.
  70
  71pce_dispatch(Options) :-
  72    with_mutex(pce_dispatch, pce_dispatch_(Options)).
  73
  74pce_dispatch_(_) :-
  75    pce_thread(pce),
  76    !.
  77pce_dispatch_(Options) :-
  78    thread_self(Me),
  79    thread_create(pce_dispatcher(Me), _,
  80                  [ alias(pce),
  81                    debug(false)
  82                  | Options
  83                  ]),
  84    thread_get_message(pce_dispatch).
  85
  86:- dynamic
  87    end_pce_dispatcher/1.
  88
  89pce_dispatcher(Origin) :-
  90    set_pce_thread,
  91    thread_self(Me),
  92    retractall(pce:pce_thread(_)),
  93    assert(pce:pce_thread(Me)),
  94    thread_send_message(Origin, pce_dispatch),
  95    set_prolog_flag(debug_on_error, false),         % avoid the debugger
  96    set_prolog_flag(generate_debug_info, true),     % Started with false
  97    repeat,
  98        catch(pce_dispatch, E, true),
  99        (   var(E)
 100        ->  true
 101        ;   print_message(error, E)
 102        ),
 103    retract(end_pce_dispatcher(Sender)),
 104    !,
 105    thread_send_message(Sender, end_pce_dispatcher).
 106
 107end(Requester) :-
 108    assert(end_pce_dispatcher(Requester)).
 109
 110%!  pce_end_dispatch is det.
 111%
 112%   End the XPCE dispatcher loop started with pce_dispatch/1.
 113
 114pce_end_dispatch :-
 115    thread_self(Me),
 116    in_pce_thread(end(Me)),
 117    thread_get_message(end_pce_dispatcher),
 118    set_pce_thread,
 119    thread_self(Me),
 120    retractall(pce:pce_thread(_)),
 121    assert(pce:pce_thread(Me)).
 122
 123%!  pce_call(:Goal) is det.
 124%
 125%   Run Goal in the XPCE thread.
 126%
 127%   @deprecated New code should used in_pce_thread/1.
 128
 129pce_call(Goal) :-
 130    in_pce_thread(Goal).