• Kirill Smelkov's avatar
    libgolang: Teach select to accept inplace tx data · 47111d3e
    Kirill Smelkov authored
    Currently select, via _selcase, requires users to provide pointers to tx
    and rx buffers. However if element type itself can fit into a pointer
    word, we can put the element directly into _selcase and mark the case
    with a flag, that it contains inplace data instead of referring to
    external storage. This will be helpful in upcoming patch where we'll
    teach pychan to work with several element types, not only pyobject
    elements.
    
    This patch does careful introduction of _selcase.flags - in such a way
    that the size of _selcase stays the same as it was before by using
    bitfields. The .ptxrx pointer is unioned with newly introduced inplace
    uint64 .itxrx data, which is used by select instead of .ptxrx if the
    flag is set. The usage of uint64 should not increase _selcase size on
    64-bit platforms.
    
    Then _selcase.ptx() and .prx() accessors are adapted accordingly and
    the rest of the changes are corresponding test and
    _chanselect2<onstack=false> adaptation.
    
    This functionality is kind of low-level and is not exposed via any
    _selsend() or chan.sends() API changes. Whenever inplace tx should be
    used, the case should be prepared either completely manually, or with
    e.g. first calling _selsend() and then manually changing .flags and
    .itxrx.  Added test serves as the example on how to do it.
    
    Inplace rx is currently forbidden - because supporting that would require
    to drop const from casev select argument. However in the future, for
    symmetry, we might want to support that as well.
    
    P.S.
    
    Since write to selcase.itxrx requires casting pointers e.g. like this:
    
    	*(int *)&sel[0].itxrx = 12345;
    
    it breaks C99 strict aliasing and by default compiler can generate bad
    code on such pattern. To the problem we adapt the build system
    to default compiler to no-strict-aliasing (as many other projects do,
    e.g. Linux kernel) with the idea that in many cases where strict
    aliasing was intended to help it actually does not, because e.g. pointer
    types are the same, while explicitly marking pointers with `restrict`
    keyword does help indeed.
    
    Nothing new for Python2 here, as it is using -fno-strict-aliasing by
    itself. However Python3 is compiling without -fno-strict-aliasing:
    https://python.org/dev/peps/pep-3123 .
    47111d3e
libgolang.cpp 35.5 KB