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;