This page is part of the web mail archives of SRFI 50 from before July 7th, 2015. The new archives for SRFI 50 contain all messages, not just those from before July 7th, 2015.
>>>>> "Tom" == Tom Lord <lord@xxxxxxx> writes: Tom> jimb is correct. Right. I misunderstood him. Thanks for the clarifying example! Tom> Consider the code: Tom> scheme_value x; Tom> [...] Tom> GCPRO(&x); Tom> [...] Tom> z = SCHEME_CONS (x, y); /* XXX */ Tom> during execution of the the statement marked "XXX", the sequence Tom> over time of operations may be: Tom> thread 1: thread 2: Tom> | Tom> reg1 = x; - t Tom> reg2 = y; - i Tom> - trigger GC m Tom> call SCHEME_CONS - e Tom> (on return, - | Tom> reg1 holds new pair) - V Tom> - trigger GC Tom> z = reg1 - Tom> At the first GC, a stop-and-copy GC will want to modify the values Tom> stored in x and y, but it won't find reg1 and reg2. Tom> At the second GC, a stop-and-copy GC will want to modify the value Tom> about to be stored in z, but it won't find reg1. Tom> That is one reason why it isn't sufficient to make sure that protected Tom> scheme values are always stored in GCPROtected locations -- you must Tom> also make sure that, other than in the internals of the FFI Tom> implementation, they are not stored anywhere else. Tom> You can make that guarantee by not passing or returning those values Tom> directly at all -- but instead passing and returning "handles" for Tom> those values. Tom> Jimb and I have each shown a technique (so now you have two available) Tom> for always passing and returning handles: in jimb's approach, handles Tom> are separately allocated objects; in my approach, handles are the Tom> addresses of GCPROtected values. So you have either: Tom> scheme_value_handle x = 0; Tom> scheme_value_handle y = 0; Tom> scheme_value_handle z = 0; Tom> [....] Tom> z = SCHEME_CONS (this_call, x, y); Tom> /* caller frees any handles allocated above. */ Tom> or: Tom> struct my_frame Tom> { Tom> scheme_value x; Tom> scheme_value y; Tom> scheme_value z; Tom> } f; Tom> GCPRO_FRAME (f); Tom> [...] Tom> SCHEME_CONS (&f.z, this_instance, &f.x, &f.y); Tom> /* eventual GCUNPRO_FRAME needed */ Tom> (As I said elsewhere, I think that there are some performance and, Tom> more importantly, GC-precision advantages to the second approach.) Tom> Either approach also has advantages for single-threaded systems simply Tom> because they both make it harder to make certain kinds of mistakes Tom> that will lead to subtle and difficult-to-reproduce GC bugs. Tom> -t -- Cheers =8-} Mike Friede, Völkerverständigung und überhaupt blabla