At 9:35 PM -0800 3/4/2000, Martin Buchholz wrote:
What's going on is just as tricky - merely less annoying to code.
You still must resist the urge to write
{
return bar (Fcons (Qnil, Qnil));
}
A function can't return a Protected_Lisp_Object, only a Lisp_Object.
I'd like you to prove me wrong - in this case I would support the
permanent switch to C++.
I think it would be possible to do this right. It seems like it
would be possible to write a C++ class that would encapsulate a GC
protected a lisp object. You'd have to have a new way to record the
currently protected objects (instead of using a linked list of
structs on stack frames) since the object would outlive the method
(and hence stack frame) that created it but this wouldn't be
impossible.
This new class would work much like the _variant_t class defined in
MSVC 6.0 works. The _variant_t class is based in the VARIANT struct
and contains no data or virtual methods of its own (so the storage
layout of a _variant_t is identical to VARIANT and it can trivially
be converted to a VARIANT). Its constructor initializes the VARIANT
and its destructor cleans up the VARIANT. There are similar
encapsulations for BSTRs (_bstr_t) and pointers to COM interfaces
(which are more complex template classes since they need to know the
nature of the interface being encapsulated).
In the XEmacs case the data being encapsulated would be a lisp object
so that Protected_Lisp_Object could be used interchangeably with
Lisp_Object (more precisely there would be trivial conversion methods
that would allow this). If Fcons returns a Protected_Lisp_Object and
bar takes a Lisp_Object (or a Protected_Lisp_Object) as a parameter,
your example above should work ok. When the temporary that holds the
return value of Fcons goes out of scope the destructor for the
Protected_Lisp_Object would unprotect the object. If bar made a copy
of its parameter in a Protected_Lisp_Object that outlives the call to
bar, then the object would still be GC protected, otherwise it
wouldn't be (which is what you want).
This is an example of using "smart pointers" in C++ (although what is
being encapsulated isn't really a pointer so the name is a bit
misleading). There is a brief discussion of this in section 11.10
and 11.11 of the third edition of Stroustrup's "The C++ Programming
Language". Implementing protected lisp objects this way wouldn't be
exactly trivial, but it wouldn't be really hard either. If all lisp
objects in C (really C++) code were changed to Protected_Lisp_Object,
GC protection would probably be essentially automatic. In fact the
best way would probably to just make Lisp_Object the class name so it
would mostly require no source code changes.
I'm designing this off the top of my head here, so I'm probably
missing something obvious, but it seems like this could be made to
work.
Mike