Generated by Cython 0.29b1

Yellow lines hint at Python interaction.
Click on a line that starts with a "`+`" to see the C code that Cython generated for it.

Raw output: test.c

     001: #cython: language_level = 3

     002: from cython.parallel import parallel

     003: from libc.stdio cimport printf

     004: """

     005:     GOAL: implement nogil option in cdef class (extension types)

     006:     and native memory manager (refcount based) that does not

     007:     depend on cpython's memory manager and that does not require GIL.

     008:

     009:     HINT: look at C++ standard library (that works very nicely with Cython)

     010:

     011:     Cython documentation if here: http://docs.cython.org/en/latest/

     012:

     013:     Basic usage: http://docs.cython.org/en/latest/src/quickstart/build.html

     014:

     015:     Tutorial: http://docs.cython.org/en/latest/src/tutorial/cython_tutorial.html

     016:

     017:     Language: http://docs.cython.org/en/latest/src/userguide/language_basics.html

     018:

     019:     Extension types: http://docs.cython.org/en/latest/src/userguide/extension_types.html

     020:

     021:         Extension Types are the "pure cython" classes that I want to be able to

     022:         use without depending on cpython GIL (and in essence runtime, memory manager, etc.)

     023:

     024:     Cython memory allocation: http://docs.cython.org/en/latest/src/tutorial/memory_allocation.html

     025:

     026:     Parallelism: http://docs.cython.org/en/latest/src/userguide/parallelism.html

     027:

     028:         Explains how nogil is posisble in cython for anything that

     029:         only relies on C libraries that are multi-threaded

     030: """

     031:

     032:

     033:

     034: # cdef class SomeMemory:

    +035: cdef class SomeMemory nogil:

    struct __pyx_obj_4test_SomeMemory {
      // nogil
      size_t ob_refcnt;
      struct __pyx_vtabstruct_4test_SomeMemory *__pyx_vtab;
      double a;
      double b;
    };

    struct __pyx_vtabstruct_4test_SomeMemory {
      void (*foo)(struct __pyx_obj_4test_SomeMemory *);
    };
    static struct __pyx_vtabstruct_4test_SomeMemory *__pyx_vtabptr_4test_SomeMemory;

     036:   """

     037:   This is a cdef class which is also called

     038:   a extensino type. It is a kind of C struct

     039:   that also acts as a python object.

     040:

     041:   We would like to be able to define "nogil"

     042:   extension types:

     043:

     044:   cdef class SomeMemory nogil:

     045:

     046:   where all methods are "nogil" and memory

     047:   allocation does not depend on python runtime

     048:   """

     049:   cdef double a;

     050:   cdef double b;

     051:

    +052:   cdef void foo(self) nogil:

    static void __pyx_f_4test_10SomeMemory_foo(struct __pyx_obj_4test_SomeMemory *__pyx_v_self) {
    /* … */
      /* function exit code */
    }

     053:     """

     054:     It is possible to define native C/Cython methods

     055:     that release the GIL (cool...)

     056:     """

    +057:     while 1:

      while (1) {

    +058:       self.a += 1

        __pyx_v_self->a = (__pyx_v_self->a + 1.0);
      }

     059:

     060:   # Not allowed to define pure Python function in the extension type with nogil option now

     061:   # since we want this extension type is CPython free

     062:   # def baz(self):

     063:   #  """

     064:   #  It is also possible to define standard python

     065:   #  methods

     066:   #  """

     067:   #  pass

     068:

     069:

     070: # cdef bar(): # it is currently impossible to release GIL

    +071: cdef double bar() nogil: # yet this is what we would like to

    static double __pyx_f_4test_bar(void) {
      struct __pyx_obj_4test_SomeMemory *__pyx_v_o1 = 0;
      struct __pyx_obj_4test_SomeMemory *__pyx_v_o2 = 0;
      double __pyx_r;
    /* … */
      /* function exit code */
      __pyx_L0:;
      return __pyx_r;
    }

     072:     """

     073:     This is a pure "cython method" which we would like to

     074:     be able to declare with nogil option but this requires

     075:     to first introduce the concept of nogil in cdef class

     076:     """

     077:     # cdef SomeMemory o = SomeMemory(42.0, 3.14) # for this we need class allocation to handle memory without libpython

    +078:     cdef SomeMemory o1 = SomeMemory(1, 1.0)

      __pyx_t_1 = (struct __pyx_obj_4test_SomeMemory *)malloc(sizeof(struct __pyx_obj_4test_SomeMemory));
      __pyx_t_1->a = 1.0;
      __pyx_t_1->b = 1.0;
      __pyx_v_o1 = __pyx_t_1;

    +079:     cdef SomeMemory o2 = SomeMemory(2, 2.0)

      __pyx_t_1 = (struct __pyx_obj_4test_SomeMemory *)malloc(sizeof(struct __pyx_obj_4test_SomeMemory));
      __pyx_t_1->a = 2.0;
      __pyx_t_1->b = 2.0;
      __pyx_v_o2 = __pyx_t_1;

    +080:     with nogil, parallel():

      {
          #ifdef WITH_THREAD
          PyThreadState *_save;
          Py_UNBLOCK_THREADS
          __Pyx_FastGIL_Remember();
          #endif
          /*try:*/ {
            {
                #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
                    #undef likely
                    #undef unlikely
                    #define likely(x)   (x)
                    #define unlikely(x) (x)
                #endif
                #ifdef _OPENMP
                #pragma omp parallel
                #endif /* _OPENMP */
                {
    /* … */
          /*finally:*/ {
            /*normal exit:*/{
              #ifdef WITH_THREAD
              __Pyx_FastGIL_Forget();
              Py_BLOCK_THREADS
              #endif
              goto __pyx_L5;
            }
            __pyx_L5:;
          }
      }

    +081:       o1.foo()

                    __pyx_f_4test_10SomeMemory_foo(__pyx_v_o1);

    +082:       o2.foo()

                    __pyx_f_4test_10SomeMemory_foo(__pyx_v_o2);
                }
            }
            #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
                #undef likely
                #undef unlikely
                #define likely(x)   __builtin_expect(!!(x), 1)
                #define unlikely(x) __builtin_expect(!!(x), 0)
            #endif
          }

     083:     # o.foo() # and we need method selection to be independent of libpython

     084:     # o.foo1(2)

     085:     # o.a = 2.732

     086:     # o.fact(100)

     087:

    +088:     return o1.a

      __pyx_r = __pyx_v_o1->a;
      goto __pyx_L0;

     089:

    +090: cpdef baz():

    static PyObject *__pyx_pw_4test_1baz(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
    static PyObject *__pyx_f_4test_baz(CYTHON_UNUSED int __pyx_skip_dispatch) {
      PyObject *__pyx_r = NULL;
      __Pyx_RefNannyDeclarations
      __Pyx_RefNannySetupContext("baz", 0);
    /* … */
      /* function exit code */
      __pyx_L1_error:;
      __Pyx_XDECREF(__pyx_t_1);
      __Pyx_AddTraceback("test.baz", __pyx_clineno, __pyx_lineno, __pyx_filename);
      __pyx_r = 0;
      __pyx_L0:;
      __Pyx_XGIVEREF(__pyx_r);
      __Pyx_RefNannyFinishContext();
      return __pyx_r;
    }

    /* Python wrapper */
    static PyObject *__pyx_pw_4test_1baz(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
    static char __pyx_doc_4test_baz[] = "\n    This method is both callable from python and pure \"cython\".\n    It can call both cdef methods and usual python functions\n    ";
    static PyObject *__pyx_pw_4test_1baz(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {
      PyObject *__pyx_r = 0;
      __Pyx_RefNannyDeclarations
      __Pyx_RefNannySetupContext("baz (wrapper)", 0);
      __pyx_r = __pyx_pf_4test_baz(__pyx_self);

      /* function exit code */
      __Pyx_RefNannyFinishContext();
      return __pyx_r;
    }

    static PyObject *__pyx_pf_4test_baz(CYTHON_UNUSED PyObject *__pyx_self) {
      PyObject *__pyx_r = NULL;
      __Pyx_RefNannyDeclarations
      __Pyx_RefNannySetupContext("baz", 0);
      __Pyx_XDECREF(__pyx_r);
      __pyx_t_1 = __pyx_f_4test_baz(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 90, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_r = __pyx_t_1;
      __pyx_t_1 = 0;
      goto __pyx_L0;

      /* function exit code */
      __pyx_L1_error:;
      __Pyx_XDECREF(__pyx_t_1);
      __Pyx_AddTraceback("test.baz", __pyx_clineno, __pyx_lineno, __pyx_filename);
      __pyx_r = NULL;
      __pyx_L0:;
      __Pyx_XGIVEREF(__pyx_r);
      __Pyx_RefNannyFinishContext();
      return __pyx_r;
    }

     091:     """

     092:     This method is both callable from python and pure "cython".

     093:     It can call both cdef methods and usual python functions

     094:     """

    +095:     return bar()

      __Pyx_XDECREF(__pyx_r);
      __pyx_t_1 = PyFloat_FromDouble(__pyx_f_4test_bar()); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 95, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_r = __pyx_t_1;
      __pyx_t_1 = 0;
      goto __pyx_L0;

     096:

    +097: def bag():

    /* Python wrapper */
    static PyObject *__pyx_pw_4test_3bag(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
    static PyMethodDef __pyx_mdef_4test_3bag = {"bag", (PyCFunction)__pyx_pw_4test_3bag, METH_NOARGS, 0};
    static PyObject *__pyx_pw_4test_3bag(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {
      PyObject *__pyx_r = 0;
      __Pyx_RefNannyDeclarations
      __Pyx_RefNannySetupContext("bag (wrapper)", 0);
      __pyx_r = __pyx_pf_4test_2bag(__pyx_self);

      /* function exit code */
      __Pyx_RefNannyFinishContext();
      return __pyx_r;
    }

    static PyObject *__pyx_pf_4test_2bag(CYTHON_UNUSED PyObject *__pyx_self) {
      PyObject *__pyx_r = NULL;
      __Pyx_RefNannyDeclarations
      __Pyx_RefNannySetupContext("bag", 0);
    /* … */
      /* function exit code */
      __pyx_L1_error:;
      __Pyx_XDECREF(__pyx_t_1);
      __Pyx_XDECREF(__pyx_t_2);
      __Pyx_AddTraceback("test.bag", __pyx_clineno, __pyx_lineno, __pyx_filename);
      __pyx_r = NULL;
      __pyx_L0:;
      __Pyx_XGIVEREF(__pyx_r);
      __Pyx_RefNannyFinishContext();
      return __pyx_r;
    }
    /* … */
      __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_4test_3bag, NULL, __pyx_n_s_test); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 97, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (PyDict_SetItem(__pyx_d, __pyx_n_s_bag, __pyx_t_1) < 0) __PYX_ERR(0, 97, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    /* … */
      __pyx_codeobj_ = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_test_pyx, __pyx_n_s_bag, 97, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj_)) __PYX_ERR(0, 97, __pyx_L1_error)

    +098:     return str(baz())

      __Pyx_XDECREF(__pyx_r);
      __pyx_t_1 = __pyx_f_4test_baz(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 98, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyUnicode_Type)), __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 98, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_r = __pyx_t_2;
      __pyx_t_2 = 0;
      goto __pyx_L0;

     099:

     100: # We call here a cpdef function, which calls a def function

     101: # which then allocates cdef class SomeMemory

    +102: print(bag())

      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_bag); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 102, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 102, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 102, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    +103: print("done")

      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_print, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 103, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;