PyGreenletUnswitchable.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
  2. /**
  3. Implementation of the Python slots for PyGreenletUnswitchable_Type
  4. */
  5. #ifndef PY_GREENLET_UNSWITCHABLE_CPP
  6. #define PY_GREENLET_UNSWITCHABLE_CPP
  7. #define PY_SSIZE_T_CLEAN
  8. #include <Python.h>
  9. #include "structmember.h" // PyMemberDef
  10. #include "greenlet_internal.hpp"
  11. // Code after this point can assume access to things declared in stdint.h,
  12. // including the fixed-width types. This goes for the platform-specific switch functions
  13. // as well.
  14. #include "greenlet_refs.hpp"
  15. #include "greenlet_slp_switch.hpp"
  16. #include "greenlet_thread_support.hpp"
  17. #include "TGreenlet.hpp"
  18. #include "TGreenlet.cpp"
  19. #include "TGreenletGlobals.cpp"
  20. #include "TThreadStateDestroy.cpp"
  21. using greenlet::LockGuard;
  22. using greenlet::LockInitError;
  23. using greenlet::PyErrOccurred;
  24. using greenlet::Require;
  25. using greenlet::g_handle_exit;
  26. using greenlet::single_result;
  27. using greenlet::Greenlet;
  28. using greenlet::UserGreenlet;
  29. using greenlet::MainGreenlet;
  30. using greenlet::BrokenGreenlet;
  31. using greenlet::ThreadState;
  32. using greenlet::PythonState;
  33. #include "PyGreenlet.hpp"
  34. static PyGreenlet*
  35. green_unswitchable_new(PyTypeObject* type, PyObject* UNUSED(args), PyObject* UNUSED(kwds))
  36. {
  37. PyGreenlet* o =
  38. (PyGreenlet*)PyBaseObject_Type.tp_new(type, mod_globs->empty_tuple, mod_globs->empty_dict);
  39. if (o) {
  40. new BrokenGreenlet(o, GET_THREAD_STATE().state().borrow_current());
  41. assert(Py_REFCNT(o) == 1);
  42. }
  43. return o;
  44. }
  45. static PyObject*
  46. green_unswitchable_getforce(PyGreenlet* self, void* UNUSED(context))
  47. {
  48. BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
  49. return PyBool_FromLong(broken->_force_switch_error);
  50. }
  51. static int
  52. green_unswitchable_setforce(PyGreenlet* self, PyObject* nforce, void* UNUSED(context))
  53. {
  54. if (!nforce) {
  55. PyErr_SetString(
  56. PyExc_AttributeError,
  57. "Cannot delete force_switch_error"
  58. );
  59. return -1;
  60. }
  61. BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
  62. int is_true = PyObject_IsTrue(nforce);
  63. if (is_true == -1) {
  64. return -1;
  65. }
  66. broken->_force_switch_error = is_true;
  67. return 0;
  68. }
  69. static PyObject*
  70. green_unswitchable_getforceslp(PyGreenlet* self, void* UNUSED(context))
  71. {
  72. BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
  73. return PyBool_FromLong(broken->_force_slp_switch_error);
  74. }
  75. static int
  76. green_unswitchable_setforceslp(PyGreenlet* self, PyObject* nforce, void* UNUSED(context))
  77. {
  78. if (!nforce) {
  79. PyErr_SetString(
  80. PyExc_AttributeError,
  81. "Cannot delete force_slp_switch_error"
  82. );
  83. return -1;
  84. }
  85. BrokenGreenlet* broken = dynamic_cast<BrokenGreenlet*>(self->pimpl);
  86. int is_true = PyObject_IsTrue(nforce);
  87. if (is_true == -1) {
  88. return -1;
  89. }
  90. broken->_force_slp_switch_error = is_true;
  91. return 0;
  92. }
  93. static PyGetSetDef green_unswitchable_getsets[] = {
  94. /* name, getter, setter, doc, closure (context pointer) */
  95. {
  96. .name="force_switch_error",
  97. .get=(getter)green_unswitchable_getforce,
  98. .set=(setter)green_unswitchable_setforce,
  99. .doc=NULL
  100. },
  101. {
  102. .name="force_slp_switch_error",
  103. .get=(getter)green_unswitchable_getforceslp,
  104. .set=(setter)green_unswitchable_setforceslp,
  105. .doc=nullptr
  106. },
  107. {.name=nullptr}
  108. };
  109. PyTypeObject PyGreenletUnswitchable_Type = {
  110. .ob_base=PyVarObject_HEAD_INIT(NULL, 0)
  111. .tp_name="greenlet._greenlet.UnswitchableGreenlet",
  112. .tp_dealloc= (destructor)green_dealloc, /* tp_dealloc */
  113. .tp_flags=G_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  114. .tp_doc="Undocumented internal class", /* tp_doc */
  115. .tp_traverse=(traverseproc)green_traverse, /* tp_traverse */
  116. .tp_clear=(inquiry)green_clear, /* tp_clear */
  117. .tp_getset=green_unswitchable_getsets, /* tp_getset */
  118. .tp_base=&PyGreenlet_Type, /* tp_base */
  119. .tp_init=(initproc)green_init, /* tp_init */
  120. .tp_alloc=PyType_GenericAlloc, /* tp_alloc */
  121. .tp_new=(newfunc)green_unswitchable_new, /* tp_new */
  122. .tp_free=PyObject_GC_Del, /* tp_free */
  123. .tp_is_gc=(inquiry)green_is_gc, /* tp_is_gc */
  124. };
  125. #endif