1 |
|
Overview |
2 |
|
======== |
3 |
|
|
4 |
|
Proposed new procedures: |
5 |
|
|
6 |
|
with-continuation-barrier, implemented by |
7 |
|
scm_with_continuation_barrier in C. Takes 2 SCM arguments: a body |
8 |
|
thunk and an exception handler procedure. The body is executed inside |
9 |
|
a "continuation barrier" that prevents calling continuations that were |
10 |
|
created on the other side of the barrier, in either direction. |
11 |
|
Uncaught throws inside the body are caught by the handler, in the |
12 |
|
style of scm_internal_catch. |
13 |
|
|
14 |
|
Two additional interfaces are created for use from C to give more |
15 |
|
convenient access to the exception handler: |
16 |
|
|
17 |
|
scm_c_c_continuation_barrier (scm_t_catch_body body, void *body_data, |
18 |
|
scm_t_catch_handler handler, |
19 |
|
void *handler_data) |
20 |
|
|
21 |
|
SCM |
22 |
|
scm_c_continuation_barrier (SCM body, |
23 |
|
scm_t_catch_handler handler, |
24 |
|
void *handler_data) |
25 |
|
|
26 |
|
|
27 |
|
The new procedures would ideally exist in a module, perhaps shared |
28 |
|
with other continuation or exception handling facilities. |
29 |
|
|
30 |
|
Procedures proposed for deprecation: |
31 |
|
|
32 |
|
scm_call_with_dynamic_root implements call-with-dynamic-root |
33 |
|
scm_apply_with_dynamic_root (undocumented, unused by Guile). |
34 |
|
scm_internal_cwdr (undocumented) |
35 |
|
|
36 |
The Problem |
The Problem |
37 |
=========== |
=========== |
38 |
|
|
39 |
Certain applications embedding Guile (Scwm, Guppi) have found it |
Certain applications embedding Guile (Scwm, Guppi) have found it |
40 |
necessary to include hacked versions of scm_call_with_dynamic_root. |
necessary to include hacked versions of scm_call_with_dynamic_root |
41 |
|
and/or its related procedures. |
42 |
|
|
43 |
They want to run user callbacks, but don't want the callback to be |
They want to run user callbacks, but don't want the callback to be |
44 |
able to longjmp (via exceptions or continuations) randomly in and out, |
able to longjmp (via exceptions or continuations) randomly in and out, |
142 |
(with-reentry-barrier user-proc) |
(with-reentry-barrier user-proc) |
143 |
(display "... done\n"))) |
(display "... done\n"))) |
144 |
|
|
145 |
However the jump-out example is resistent to this technique. In any |
However the jump-out example is resistant to this technique. In any |
146 |
case the interaction of dynamic-wind and continuations and exceptions |
case the interaction of dynamic-wind and continuations and exceptions |
147 |
is likely to cause strange and unstable behaviour: |
is likely to cause strange and unstable behaviour: |
148 |
|
|
171 |
continuation barrier, instead of trying to clean things up after the |
continuation barrier, instead of trying to clean things up after the |
172 |
continuation has been executed. |
continuation has been executed. |
173 |
|
|
174 |
Hence, what we really need is a method similar to dynamic-root, but |
Hence, one approach is to use a method similar to dynamic-root, but |
175 |
without using dynamic root - which will remove one obstacle to the |
without using dynamic root. |
176 |
proposed removal of the dynamic roots. |
|
177 |
|
Removing the interface for creating dynamic roots from the external |
178 |
|
API would allow dynamic roots to be limited to their use in the thread |
179 |
|
system: initially with exactly one dynamic root for each thread. The |
180 |
|
implementation could then be changed without affect on the external |
181 |
|
API. |
182 |
|
|
183 |
Proposed implementation |
Proposed implementation |
184 |
======================= |
======================= |
185 |
|
|
186 |
As in the current system, it should not be permitted to invoke a |
In the current system it's not possible to invoke a continuation that |
187 |
continuation that was captured by a different thread. This could be |
was captured by a different thread. It's not proposed to change this |
188 |
implemented by storing the current thread id in the continuation when |
convention. A possible implementation technique would be to store the |
189 |
it's captured and comparing with the current id when the continuation |
current thread id in the continuation when it's captured and compare |
190 |
is invoked. |
with the current id when the continuation is invoked. |
191 |
|
|
192 |
To implement the continuation barrier, for each thread we can have a |
To implement the continuation barrier, for each thread we can have a |
193 |
simple list representing the barrier (let's call it |
simple list representing the barrier (let's call it |
203 |
the cell currently at the head of the list. |
the cell currently at the head of the list. |
204 |
|
|
205 |
This w-c-b list comparison would also prevent cross-thread invokation, |
This w-c-b list comparison would also prevent cross-thread invokation, |
206 |
so comparison of thread-ids can be dropped. |
so the comparison of thread-ids suggested above can actually be |
207 |
|
dropped. |
208 |
|
|
209 |
An example implementation to play with is attached below. |
An example implementation to play with is attached below. |
210 |
|
|
213 |
|
|
214 |
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 |
215 |
both continuation and exception handlers. An exception handler is |
both continuation and exception handlers. An exception handler is |
216 |
needed in any case in the implementation discussed above. Such an |
needed in any case in the implementation described above. Such an |
217 |
interface in C should take at least a) the callback to be protected b) |
interface in C should take at least a) the callback to be protected b) |
218 |
and exception handler and associated handler data to be passed to |
and exception handler and associated handler data to be passed to |
219 |
scm_internal_catch. |
scm_internal_catch. |
241 |
scm_t_catch_handler handler, |
scm_t_catch_handler handler, |
242 |
void *handler_data) |
void *handler_data) |
243 |
|
|
244 |
Should the facility be provide at the Scheme level too, or just in C? |
Should the facility be provided at the Scheme level too, or just in C? |
245 |
There's no obvious reason to restrict the application of callbacks to |
There's no obvious reason to restrict the use of callbacks to C, hence |
246 |
C, hence there is a third variant that takes two SCM arguments: |
there is a third variant that takes two SCM arguments: |
247 |
|
|
248 |
SCM_DEFINE (scm_with_continuation_barrier, "with-continuation-barrier", |
SCM_DEFINE (scm_with_continuation_barrier, "with-continuation-barrier", |
249 |
2, 0, 0, |
2, 0, 0, |
286 |
coop thread spawning, which will benefit by simplification of the |
coop thread spawning, which will benefit by simplification of the |
287 |
scm_root struct. |
scm_root struct. |
288 |
|
|
289 |
To do |
Module system |
290 |
===== |
============= |
291 |
|
|
292 |
|
New interfaces should probably be in a separate module, to allow later |
293 |
|
modifications to the interface without breaking old code -- e.g., by |
294 |
|
adding a new module with a new name, if versioning isn't available. |
295 |
|
However to make this work in C too, the module needs to be a separate |
296 |
|
dynamic library, which reduces the convenience of use. Perhaps it |
297 |
|
could be combined into a module with related non-R5RS continuation or |
298 |
|
catch/throw facilities. |
299 |
|
|
300 |
|
Unknowns |
301 |
|
======== |
302 |
|
|
303 |
error handling and reporting (stack trace?), more on convenience of |
Does anything need to be done for error handling and reporting (e.g., |
304 |
use (e.g., try it out in Guppi). |
stack trace?) This may be a topic for a separate discussion. |
305 |
|
|
306 |
References |
References |
307 |
========== |
========== |