/[guile]/guile/guile-core/devel/extension/dynamic-root.text
ViewVC logotype

Diff of /guile/guile-core/devel/extension/dynamic-root.text

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by ghouston, Tue Dec 4 15:10:16 2001 UTC revision 1.4 by ghouston, Thu Feb 28 00:23:08 2002 UTC
# Line 21  considerations are how any new interface Line 21  considerations are how any new interface
21  and reporting; whether a new interface is convenient to use from C;  and reporting; whether a new interface is convenient to use from C;
22  whether a new interface should also be available to Scheme code.  whether a new interface should also be available to Scheme code.
23    
24    Example
25    =======
26    
27    We have a procdure that executes a procedure supplied by a user.
28    It's essential that the code before and after the user-proc is
29    executed in the right order: maybe it's C code that opens and
30    closes files or allocates/frees memory:
31    
32    (define break-me (lambda (user-proc)
33                       (display "executing user ...\n")
34                       (user-proc)
35                       (display "... done\n")))
36    
37    Now the user types:
38    
39    (define cont #f)
40    (break-me (lambda ()
41                (call-with-current-continuation (lambda (c)
42                                                  (set! cont c)))))
43    
44    giving:
45    
46    "executing user ...
47    ... done"
48    
49    but then:
50    
51    (cont #f) gives:
52    
53    "... done"
54    
55  Discussion  Discussion
56  ==========  ==========
57    
58  There are two ways that longjmp may be invoked from a Scheme callback:  There are two ways that longjmp may be invoked from a Scheme callback:
59  raising an exception or invoking a continuation.  Exceptions can be  raising an exception or invoking a continuation.  Exceptions can be
60  caught using scm_internal_catch, so it could be argued that the new  caught using scm_internal_catch, but a primitive "continuation
61  interface only needs to block continuations.  barrier" is lacking. However such a barrier can be easily created
62    using dynamic-wind, assuming that an error can be signalled within the
63  However there are two problems with this: firstly it's unlikely that  before- thunk:
64  anybody would want to block continuations without also catching  
65  exceptions, so it's more convenient to use a single facility set up  (define with-continuation-barrier
66  both types of blocking.  Secondly, the fact that exceptions and    (lambda (thunk)
67  continuations can be treated separately in Guile is just an      (let ((entered #f))
68  implementation detail: in general in Scheme it's possible to use        (dynamic-wind
69  continuations to implement an exception mechanism, and it's            (lambda ()
70  undesirable to tie a new language feature to an implementation detail              (if entered
71  when it can be avoided, even at the C level.                  (error "Attempt to break continuation barrier")
72                    (set! entered #t)))
73  Hence, the interface should take at least a) the callback to be            thunk
74  protected b) and exception handler and associated handler data to be            (lambda () #f)))))
75  passed to scm_internal_catch.  
76    The example above can now be fixed:
77  On which side of the continuation barrier should be exception handler  
78  be installed?  Logically it belongs on the same side as the callback:  (define break-me (lambda (user-proc)
79  i.e., if the callback raises an exception then the handler can catch                     (display "executing user ...\n")
80  it without crossing it the continuation barrier.  But what happens if                     (with-continuation-barrier user-proc)
81  the handler raises another exception?  This doesn't seem like an                     (display "... done\n")))
82  important concern, since the hander is under control of the code that  
83  is trying to protect itself.  It should be sufficient to warn in the  The interesting problem is the interaction between exceptions and
84  documentation that such exceptions produce undefined behaviour and  continations.  While exceptions that occur in user code should be
85  allow them to cross the continuation barrier.  caught so that the cleanup code can be executed, the cleanup code
86    should not be called for the exception raised by
87    with-continuation-barrier itself.  Thus the exception handler needs to
88    go inside the continuation barrier.  This also avoids any assumption
89    that exceptions can pass through the continuation barrier, i.e.,
90    current Guile behaviour where exceptions are indendent of
91    continuations.
92    
93    A problem with this is that an outer exception handler would catch
94    both exceptions from the user code and exceptions generated by the
95    continuation barrier: i.e., possibly more than once for a given
96    invocation.  The current call-with-dynamic-root implementation avoids
97    this by refusing to invoke mismatching continuations in the first
98    place, by examining a sequence number in the dynamic root.  However
99    it's not clear that presence of the dynamic root implementation is
100    something that can be relied on in the long term.
101    
102    (define (break-me user-proc)
103      (catch #t
104             (lambda ()
105               (display "executing user ...\n")
106               (with-continuation-barrier user-proc)
107               (display "... done\n"))
108             (lambda args
109               (display "outer catch!\n")
110               (write args))))
111    
112    guile> (define cont #f)
113    (break-me (lambda ()
114                (call-with-current-continuation (lambda (c)
115                                                  (set! cont c)))))
116    
117    guile> executing user ...
118    ... done
119    guile> (cont #f)
120    Segmentation fault
121    
122    Hmmm, it's even worse than I thought.
123    
124    For ease of use, we would like to have a single facility to set up
125    both continuation and exception handlers.  Such an interface should
126    take at least a) the callback to be protected b) and exception handler
127    and associated handler data to be passed to scm_internal_catch.
128    
129  How should the callback procedure be passed to the interface and  How should the callback procedure be passed to the interface and
130  invoked?  Should it be like scm_internal_catch where it's passed as a  invoked?  Should it be like scm_internal_catch where it's passed as a
# Line 82  the body, unless an exception occurred i Line 155  the body, unless an exception occurred i
155  of calling the handler.  So the return type is SCM, as for  of calling the handler.  So the return type is SCM, as for
156  scm_internal_catch.  scm_internal_catch.
157    
158  Yet to be discussed: libguile usage and threads, error handling and  To do
159  reporting, convenience of use, Scheme-level interface.  =====
160    
161    libguile usage and threads, error handling and reporting, convenience
162    of use, Scheme-level interface.

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26