• Kirill Smelkov's avatar
    time: Switch internals to pyx/nogil · 8c2ac5e9
    Kirill Smelkov authored
    - use .c.chan_double() which gives chan[double] pyx/nogil way to access
      Ticker.c and Timer.c. Use the channels via pyx/nogil API from inside.
    - use pyx/nogil sleep and now;
    
    This gets time.pyx codebase closer to be used from pyx/nogil mode.
    
    NOTE: unless something like pyx/nogil memory management emerges[1] we
    are relying on Python to manage memory of Ticker and Timer classes.
    If we just spawn e.g. Ticker.__tick via pyx/nogil go, the thread that is
    spawned won't be holding a reference to Ticker object, and once the
    ticker goes out of scope in original thread (while its channel .c might
    be still in scope), __tick will segfault accessing freed Ticker object.
    
    To workaround it we use the following pattern:
    
        nogilready = chan(dtype='C.structZ')
        pygo(mymeth)
        nogilready.recv()
    
        def mymeth(MyObject self, pychan nogilready)
            with nogil:
                nogilready.chan_structZ().close()
                self._mymeth()
        cdef void _mymeth(MyObject self) nogil:
            ...
    
    where python reference to MyObject will be held in spawned thread during
    its lifetime, while the service provided by mymeth will be done under
    nogil.
    
    [1] https://www.nexedi.com/blog/NXD-Document.Blog.Cypclass
    8c2ac5e9
_time.pyx 8.2 KB