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

Diff of /guile/workbook/extension/dynamic-root.text

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

revision 1.1 by ttn, Sun Mar 24 00:20:19 2002 UTC revision 1.2 by ghouston, Mon Apr 8 19:37:02 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    Another thing to consider is whether the implementation of this feature
25    is always going to be tied to the dynamic-root concept, or whether
26    it could be implemented in some other way.
27    
28    Finally, there is the consideration of whether all this is just more
29    trouble than it's worth: perhaps the applications that want this
30    feature should either a) protect their code properly against Scheme
31    flow-control b) forbid use of call/cc in callbacks c) forbid accessing
32    the top-level environment in callbacks.
33    
34  Example  Example
35  =======  =======
36    
37  We have a procdure that executes a procedure supplied by a user.  We have some code that executes a procedure supplied by a user.
38  It's essential that the code before and after the user-proc is  It's essential that the code before and after the user-proc is
39  executed in the right order: maybe it's C code that opens and  executed in the right order: maybe it's C code that opens and
40  closes files or allocates/frees memory:  closes files or allocates/frees memory:
# Line 52  but then: Line 62  but then:
62    
63  "... done"  "... done"
64    
65    i.e., the user has jumped back into the callback via a continuation.
66    
67    Alternatively, the user can jump out of the callback:
68    
69    (define cont #f)
70    (call-with-current-continuation (lambda (c) (set! cont c)))
71    (break-me (lambda ()
72                (cont)))
73    
74  Discussion  Discussion
75  ==========  ==========
76    
77  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:
78  raising an exception or invoking a continuation.  Exceptions can be  raising an exception or invoking a continuation.  Exceptions can be
79  caught using scm_internal_catch, but a primitive "continuation  caught using scm_internal_catch, but a primitive "continuation
80  barrier" is lacking. However such a barrier can be easily created  barrier" is lacking. A reentry barrier can be easily created
81  using dynamic-wind, assuming that an error can be signalled within the  using dynamic-wind, assuming that an error can be signalled within the
82  before- thunk:  before- thunk:
83    
84  (define with-continuation-barrier  (define with-reentry-barrier
85    (lambda (thunk)    (lambda (thunk)
86      (let ((entered #f))      (let ((entered #f))
87        (dynamic-wind        (dynamic-wind
88            (lambda ()            (lambda ()
89              (if entered              (if entered
90                  (error "Attempt to break continuation barrier")                  (error "Attempt to break reentry barrier")
91                  (set! entered #t)))                  (set! entered #t)))
92            thunk            thunk
93            (lambda () #f)))))            (lambda () #f)))))
94    
95  The example above can now be fixed:  The jump-back-in example above may now be fixed:
96    
97  (define break-me (lambda (user-proc)  (define break-me (lambda (user-proc)
98                     (display "executing user ...\n")                     (display "executing user ...\n")
99                     (with-continuation-barrier user-proc)                     (with-reentry-barrier user-proc)
100                     (display "... done\n")))                     (display "... done\n")))
101    
102  The interesting problem is the interaction between exceptions and  However the jump-out example is resistent to this technique.  In any
103  continations.  While exceptions that occur in user code should be  case the interaction of dynamic-wind and continuations and exceptions
104  caught so that the cleanup code can be executed, the cleanup code  is likely to cause strange and unstable behaviour:
 should not be called for the exception raised by  
 with-continuation-barrier itself.  Thus the exception handler needs to  
 go inside the continuation barrier.  This also avoids any assumption  
 that exceptions can pass through the continuation barrier, i.e.,  
 current Guile behaviour where exceptions are indendent of  
 continuations.  
   
 A problem with this is that an outer exception handler would catch  
 both exceptions from the user code and exceptions generated by the  
 continuation barrier: i.e., possibly more than once for a given  
 invocation.  The current call-with-dynamic-root implementation avoids  
 this by refusing to invoke mismatching continuations in the first  
 place, by examining a sequence number in the dynamic root.  However  
 it's not clear that presence of the dynamic root implementation is  
 something that can be relied on in the long term.  
105    
106  (define (break-me user-proc)  guile> (define (break-me user-proc)
107    (catch #t    (catch #t
108           (lambda ()           (lambda ()
109             (display "executing user ...\n")             (display "executing user ...\n")
110             (with-continuation-barrier user-proc)             (with-reentry-barrier user-proc)
111             (display "... done\n"))             (display "... done\n"))
112           (lambda args           (lambda args
113             (display "outer catch!\n")             (display "outer catch!\n")
# Line 119  guile> executing user ... Line 123  guile> executing user ...
123  guile> (cont #f)  guile> (cont #f)
124  Segmentation fault  Segmentation fault
125    
126  Hmmm, it's even worse than I thought.  The existing dynamic-root method avoids such difficulties by
127    preventing the execution of continuations that would cross the
128    continuation barrier, instead of trying to clean things up after the
129    continuation has been executed.
130    
131  For ease of use, we would like to have a single facility to set up  For ease of use, we would like to have a single facility to set up
132  both continuation and exception handlers.  Such an interface should  both continuation and exception handlers.  Such an interface should

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

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