First question: The GAP garbage collector might delete objects, or it might
move existing objects around in memory (it is a compacting garbage
collector). If your code contains C pointers to GAP objects, bad things
will happen after that. Not every libGAP_* function can invoke the garbage
collector, and for those that do it will not always run a collection cycle.
But there are no documented guarantees that any particular libGAP_*
function does not run garbage collection, or may be changed to run garbage
collection in the future.
Second question: Move the libgap_enter/exit outside of the loop, assuming
that the python functions don't themselves call libgap. If they do, you
will get a "RuntimeError: Entered a critical block twice". In that case,
move the libgap_enter/exit into the loop as far as necessary to have
non-overlapping libgap_enter/exit blocks.
Snip from docs:
Using the libGAP C library from Cython
======================================
The lower-case ``libgap_foobar`` functions are ones that we added to
make the libGAP C shared library. The ``libGAP_foobar`` methods are
the original GAP methods simply prefixed with the string
``libGAP_``. The latter were originally not designed to be in a
library, so some care needs to be taken to call them.
In particular, you must call ``libgap_mark_stack_bottom()`` in every
function that calls into the libGAP C functions. The reason is that
the GAP memory manager will automatically keep objects alive that are
referenced in local (stack-allocated) variables. While convenient,
this requires to look through the stack to find anything that looks
like an address to a memory bag. But this requires vigilance against
the following pattern::
cdef f()
libgap_mark_stack_bottom()
libGAP_function()
cdef g()
libgap_mark_stack_bottom();
f() # f() changed the stack bottom marker
libGAP_function() # boom
The solution is to re-order ``g()`` to first call ``f()``. In order to
catch this error, it is recommended that you wrap calls into libGAP in
``libgap_enter`` / ``libgap_exit`` blocks and not call
``libgap_mark_stack_bottom`` manually. So instead, always write
cdef f()
libgap_enter()
libGAP_function()
libgap_exit()
cdef g()
f()
libgap_enter()
libGAP_function()
libgap_exit()
If you accidentally call ``libgap_enter()`` twice then an error
message is printed to help you debug this::
sage: from sage.libs.gap.util import error_enter_libgap_block_twice
sage: error_enter_libgap_block_twice()
Traceback (most recent call last):
...
RuntimeError: Entered a critical block twice
On Thursday, September 7, 2017 at 2:30:29 PM UTC+2, Simon King wrote:
>
> Hi!
>
> My questions are about how/when to use libgap_enter/exit
> when calling a libGAP_* function.
>
> First question: What should happen if one doesn't use
> libgap_enter/exit? I ask since I called libGAP_EQ without
> libgap_enter/exit, but there is no crash and it just works.
> So, can one do without it, in some cases?
>
> Second question: What should one do if one has a loop
> containing both several python and libGAP_* calls? Put
> libgap_enter/exit around each individual libGAP_* call?
> Or is it possible to have Python calls (and a whole
> "for" loop) between enter and exit?
>
> Best regards,
> Simon
>
>
--
You received this message because you are subscribed to the Google Groups
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/d/optout.