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.

Reply via email to