home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!eiffel!eiffel.com
- From: ram@eiffel.com (Raphael Manfredi)
- Newsgroups: comp.lang.eiffel
- Subject: Re: CECIL and garbage collection
- Summary: New Eiffel-C interface scheme in Eiffel 3
- Keywords: memory management, Cecil, garbage collection
- Message-ID: <116@eiffel.eiffel.com>
- Date: 20 Aug 92 16:24:52 GMT
- References: <seanb.714234719@cs.man.ac.uk>
- Sender: ram@eiffel.com
- Organization: Interactive Software Engineering, Santa Barbara CA
- Lines: 110
-
- Quoting seanb@cs.man.ac.uk (Sean Bechhofer) from comp.lang.eiffel:
- >
- > "What keeps the garbage collector from collecting Eiffel
- > objects that are only referenced in C code? Nothing. If
- > garbage collection is enabled, you must keep a reference
- > on the Eiffel side to prevent an object from being collected."
- >
- > [deletion]
- >
- > o Is this "feature" likely to change in Eiffel 3?
-
- Do you want a short answer or a long answer? Both? Very well, the short answer
- is YES. This "bug" has changed in Eiffel 3.
-
- Although in your case the problem manifested itself with the use of Cecil,
- it is more general than that, as the quote from the Environment Manual which
- you reproduced above would tell us.
-
- In Eiffel 3, whenever the Eiffel side calls an external C routine or whenever
- Cecil is requested an object creation, all you get is an EIF_OBJ pointer.
- If you wish to get access to the object, you must use the eif_access() macro.
- That will give you the physical address of the object, but this pointer is not
- to be kept around as the memory manager (aka GC) has entire liberty to move
- your objects to optimize the memory usage and reduce fragmentation for instance.
- So any access via eif_access() on an EIF_OBJ pointer is safe.
-
- The compiler automatically generates code to protect your references when you
- are calling an external C routine. This protection is, by default, released
- when Eiffel regains control (but see below). Here is an example:
-
- --- Eiffel side:
-
- f (a: GENERAL): GENERAL is
- -- Call to external `f'
- external
- "C"
- end;
-
- --- C side:
-
- #include <cecil.h>
-
- char *f(x)
- EIF_OBJ x;
- {
- char *pointer = eif_access(x);
- EIF_TYPE_ID general_id;
- EIF_OBJ new_object;
-
- /* It's safe to keep 'pointer' as long as no Eiffel calls are made, and
- * no memory allocation is done.
- */
-
- ...
-
- general_id = eif_type_id("GENERAL");
- new_object = eif_create(general_id);
-
- some_function(eif_access(new_object), ...);
-
- /* Eiffel function was declared to return an object, not an EIF_OBJ! */
-
- return eif_access(new_object);
- }
-
- --- End of example
-
- Now sometimes it is necessary to have a finer control over the memory. For
- instance, if Eiffel wishes to call a C library function bcopy(), this function
- expects real pointers, not EIF_OBJ pointers! So it is possible to direct the
- compiler not to protect references given to the external function by preceding
- the variable name with a '$'. The raw reference will then be given to the C.
- Should this function call an Eiffel routine or call malloc(), chaos is to be
- expected if you ever use the reference you originally got from Eiffel again.
-
- If the C side wants to keep an EIF_OBJ pointer even after the return to Eiffel,
- it must issue the run-time call eif_adopt, which will return you a new EIF_OBJ
- pointer, owned only by the C side (the original EIF_OBJ will be released when
- the control flow returns to the Eiffel routine which issued the protection).
- As a side effect, you have the guarantee that this object will be always alive,
- even if all the references from Eiffel have been cut. Each time you want to
- access the object, you must still use eif_access().
-
- When the C side does not have any more use for an "adopted" EIF_OBJ pointer,
- it must call the run-time routine eif_wean(). Any further use of EIF_OBJ is
- forbidden once eif_wean() has been called.
-
- If you need to access a given object many times, it is possible to *freeze* its
- location in memory by calling eif_freeze(). This run-time call will return you
- a real (char *) reference which can be use freely by all the routines. The
- object will never move again. In fact, the memory management has not further
- control over this object. Even when it is dead, the GC will not collect it.
- Therefore, it is up to the programmer to call eif_unfreeze() to let the GC see
- the object again and allow it to move and/or be collected.
-
- For more information, you should read "Eiffel: The Language", paragraph 24.7
- entitled "The Cecil Library".
-
- To summarize, Eiffel 3 overcomes those memory peculiarities at the cost of a
- stronger discipline imposed to the programmer. The scheme is flexible enough
- to allow any kind of inter-connection between Eiffel and C. And this is not
- even ISE Eiffel-dependent since it is part of the Eiffel specifications which
- every Eiffel compiler must meet. However, the ISE Eiffel run-time documentation
- will probably mention some over specific low-level run-time calls which bring
- much more flexibility, at the price of a lack of portability.
- --
- Raphael Manfredi <ram@eiffel.com>
- Interactive Software Engineering Inc.
- 270 Storke Road, Suite #7 / Tel +1 (805) 685-1006 \
- Goleta, California 93117, USA \ Fax +1 (805) 685-6869 /
-