PyGreenlet.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
  2. #ifndef PYGREENLET_CPP
  3. #define PYGREENLET_CPP
  4. /*****************
  5. The Python slot functions for TGreenlet.
  6. */
  7. #define PY_SSIZE_T_CLEAN
  8. #include <Python.h>
  9. #include "structmember.h" // PyMemberDef
  10. #include "greenlet_internal.hpp"
  11. #include "TThreadStateDestroy.cpp"
  12. #include "TGreenlet.hpp"
  13. // #include "TUserGreenlet.cpp"
  14. // #include "TMainGreenlet.cpp"
  15. // #include "TBrokenGreenlet.cpp"
  16. #include "greenlet_refs.hpp"
  17. #include "greenlet_slp_switch.hpp"
  18. #include "greenlet_thread_support.hpp"
  19. #include "TGreenlet.hpp"
  20. #include "TGreenletGlobals.cpp"
  21. #include "TThreadStateDestroy.cpp"
  22. #include "PyGreenlet.hpp"
  23. // #include "TGreenlet.cpp"
  24. // #include "TExceptionState.cpp"
  25. // #include "TPythonState.cpp"
  26. // #include "TStackState.cpp"
  27. using greenlet::LockGuard;
  28. using greenlet::LockInitError;
  29. using greenlet::PyErrOccurred;
  30. using greenlet::Require;
  31. using greenlet::g_handle_exit;
  32. using greenlet::single_result;
  33. using greenlet::Greenlet;
  34. using greenlet::UserGreenlet;
  35. using greenlet::MainGreenlet;
  36. using greenlet::BrokenGreenlet;
  37. using greenlet::ThreadState;
  38. using greenlet::PythonState;
  39. static PyGreenlet*
  40. green_new(PyTypeObject* type, PyObject* UNUSED(args), PyObject* UNUSED(kwds))
  41. {
  42. PyGreenlet* o =
  43. (PyGreenlet*)PyBaseObject_Type.tp_new(type, mod_globs->empty_tuple, mod_globs->empty_dict);
  44. if (o) {
  45. new UserGreenlet(o, GET_THREAD_STATE().state().borrow_current());
  46. assert(Py_REFCNT(o) == 1);
  47. }
  48. return o;
  49. }
  50. // green_init is used in the tp_init slot. So it's important that
  51. // it can be called directly from CPython. Thus, we don't use
  52. // BorrowedGreenlet and BorrowedObject --- although in theory
  53. // these should be binary layout compatible, that may not be
  54. // guaranteed to be the case (32-bit linux ppc possibly).
  55. static int
  56. green_init(PyGreenlet* self, PyObject* args, PyObject* kwargs)
  57. {
  58. PyArgParseParam run;
  59. PyArgParseParam nparent;
  60. static const char* kwlist[] = {
  61. "run",
  62. "parent",
  63. NULL
  64. };
  65. // recall: The O specifier does NOT increase the reference count.
  66. if (!PyArg_ParseTupleAndKeywords(
  67. args, kwargs, "|OO:green", (char**)kwlist, &run, &nparent)) {
  68. return -1;
  69. }
  70. if (run) {
  71. if (green_setrun(self, run, NULL)) {
  72. return -1;
  73. }
  74. }
  75. if (nparent && !nparent.is_None()) {
  76. return green_setparent(self, nparent, NULL);
  77. }
  78. return 0;
  79. }
  80. static int
  81. green_traverse(PyGreenlet* self, visitproc visit, void* arg)
  82. {
  83. // We must only visit referenced objects, i.e. only objects
  84. // Py_INCREF'ed by this greenlet (directly or indirectly):
  85. //
  86. // - stack_prev is not visited: holds previous stack pointer, but it's not
  87. // referenced
  88. // - frames are not visited as we don't strongly reference them;
  89. // alive greenlets are not garbage collected
  90. // anyway. This can be a problem, however, if this greenlet is
  91. // never allowed to finish, and is referenced from the frame: we
  92. // have an uncollectible cycle in that case. Note that the
  93. // frame object itself is also frequently not even tracked by the GC
  94. // starting with Python 3.7 (frames are allocated by the
  95. // interpreter untracked, and only become tracked when their
  96. // evaluation is finished if they have a refcount > 1). All of
  97. // this is to say that we should probably strongly reference
  98. // the frame object. Doing so, while always allowing GC on a
  99. // greenlet, solves several leaks for us.
  100. Py_VISIT(self->dict);
  101. if (!self->pimpl) {
  102. // Hmm. I have seen this at interpreter shutdown time,
  103. // I think. That's very odd because this doesn't go away until
  104. // we're ``green_dealloc()``, at which point we shouldn't be
  105. // traversed anymore.
  106. return 0;
  107. }
  108. return self->pimpl->tp_traverse(visit, arg);
  109. }
  110. static int
  111. green_is_gc(PyObject* _self)
  112. {
  113. BorrowedGreenlet self(_self);
  114. int result = 0;
  115. /* Main greenlet can be garbage collected since it can only
  116. become unreachable if the underlying thread exited.
  117. Active greenlets --- including those that are suspended ---
  118. cannot be garbage collected, however.
  119. */
  120. if (self->main() || !self->active()) {
  121. result = 1;
  122. }
  123. // The main greenlet pointer will eventually go away after the thread dies.
  124. if (self->was_running_in_dead_thread()) {
  125. // Our thread is dead! We can never run again. Might as well
  126. // GC us. Note that if a tuple containing only us and other
  127. // immutable objects had been scanned before this, when we
  128. // would have returned 0, the tuple will take itself out of GC
  129. // tracking and never be investigated again. So that could
  130. // result in both us and the tuple leaking due to an
  131. // unreachable/uncollectible reference. The same goes for
  132. // dictionaries.
  133. //
  134. // It's not a great idea to be changing our GC state on the
  135. // fly.
  136. result = 1;
  137. }
  138. return result;
  139. }
  140. static int
  141. green_clear(PyGreenlet* self)
  142. {
  143. /* Greenlet is only cleared if it is about to be collected.
  144. Since active greenlets are not garbage collectable, we can
  145. be sure that, even if they are deallocated during clear,
  146. nothing they reference is in unreachable or finalizers,
  147. so even if it switches we are relatively safe. */
  148. // XXX: Are we responsible for clearing weakrefs here?
  149. Py_CLEAR(self->dict);
  150. return self->pimpl->tp_clear();
  151. }
  152. /**
  153. * Returns 0 on failure (the object was resurrected) or 1 on success.
  154. **/
  155. static int
  156. _green_dealloc_kill_started_non_main_greenlet(BorrowedGreenlet self)
  157. {
  158. /* Hacks hacks hacks copied from instance_dealloc() */
  159. /* Temporarily resurrect the greenlet. */
  160. assert(self.REFCNT() == 0);
  161. Py_SET_REFCNT(self.borrow(), 1);
  162. /* Save the current exception, if any. */
  163. PyErrPieces saved_err;
  164. try {
  165. // BY THE TIME WE GET HERE, the state may actually be going
  166. // away
  167. // if we're shutting down the interpreter and freeing thread
  168. // entries,
  169. // this could result in freeing greenlets that were leaked. So
  170. // we can't try to read the state.
  171. self->deallocing_greenlet_in_thread(
  172. self->thread_state()
  173. ? static_cast<ThreadState*>(GET_THREAD_STATE())
  174. : nullptr);
  175. }
  176. catch (const PyErrOccurred&) {
  177. PyErr_WriteUnraisable(self.borrow_o());
  178. /* XXX what else should we do? */
  179. }
  180. /* Check for no resurrection must be done while we keep
  181. * our internal reference, otherwise PyFile_WriteObject
  182. * causes recursion if using Py_INCREF/Py_DECREF
  183. */
  184. if (self.REFCNT() == 1 && self->active()) {
  185. /* Not resurrected, but still not dead!
  186. XXX what else should we do? we complain. */
  187. PyObject* f = PySys_GetObject("stderr");
  188. Py_INCREF(self.borrow_o()); /* leak! */
  189. if (f != NULL) {
  190. PyFile_WriteString("GreenletExit did not kill ", f);
  191. PyFile_WriteObject(self.borrow_o(), f, 0);
  192. PyFile_WriteString("\n", f);
  193. }
  194. }
  195. /* Restore the saved exception. */
  196. saved_err.PyErrRestore();
  197. /* Undo the temporary resurrection; can't use DECREF here,
  198. * it would cause a recursive call.
  199. */
  200. assert(self.REFCNT() > 0);
  201. Py_ssize_t refcnt = self.REFCNT() - 1;
  202. Py_SET_REFCNT(self.borrow_o(), refcnt);
  203. if (refcnt != 0) {
  204. /* Resurrected! */
  205. _Py_NewReference(self.borrow_o());
  206. Py_SET_REFCNT(self.borrow_o(), refcnt);
  207. /* Better to use tp_finalizer slot (PEP 442)
  208. * and call ``PyObject_CallFinalizerFromDealloc``,
  209. * but that's only supported in Python 3.4+; see
  210. * Modules/_io/iobase.c for an example.
  211. *
  212. * The following approach is copied from iobase.c in CPython 2.7.
  213. * (along with much of this function in general). Here's their
  214. * comment:
  215. *
  216. * When called from a heap type's dealloc, the type will be
  217. * decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
  218. if (PyType_HasFeature(self.TYPE(), Py_TPFLAGS_HEAPTYPE)) {
  219. Py_INCREF(self.TYPE());
  220. }
  221. PyObject_GC_Track((PyObject*)self);
  222. _Py_DEC_REFTOTAL;
  223. #ifdef COUNT_ALLOCS
  224. --Py_TYPE(self)->tp_frees;
  225. --Py_TYPE(self)->tp_allocs;
  226. #endif /* COUNT_ALLOCS */
  227. return 0;
  228. }
  229. return 1;
  230. }
  231. static void
  232. green_dealloc(PyGreenlet* self)
  233. {
  234. PyObject_GC_UnTrack(self);
  235. BorrowedGreenlet me(self);
  236. if (me->active()
  237. && me->started()
  238. && !me->main()) {
  239. if (!_green_dealloc_kill_started_non_main_greenlet(me)) {
  240. return;
  241. }
  242. }
  243. if (self->weakreflist != NULL) {
  244. PyObject_ClearWeakRefs((PyObject*)self);
  245. }
  246. Py_CLEAR(self->dict);
  247. if (self->pimpl) {
  248. // In case deleting this, which frees some memory,
  249. // somehow winds up calling back into us. That's usually a
  250. //bug in our code.
  251. Greenlet* p = self->pimpl;
  252. self->pimpl = nullptr;
  253. delete p;
  254. }
  255. // and finally we're done. self is now invalid.
  256. Py_TYPE(self)->tp_free((PyObject*)self);
  257. }
  258. static OwnedObject
  259. internal_green_throw(BorrowedGreenlet self, PyErrPieces& err_pieces)
  260. {
  261. PyObject* result = nullptr;
  262. err_pieces.PyErrRestore();
  263. assert(PyErr_Occurred());
  264. if (self->started() && !self->active()) {
  265. /* dead greenlet: turn GreenletExit into a regular return */
  266. result = g_handle_exit(OwnedObject()).relinquish_ownership();
  267. }
  268. self->args() <<= result;
  269. return single_result(self->g_switch());
  270. }
  271. PyDoc_STRVAR(
  272. green_switch_doc,
  273. "switch(*args, **kwargs)\n"
  274. "\n"
  275. "Switch execution to this greenlet.\n"
  276. "\n"
  277. "If this greenlet has never been run, then this greenlet\n"
  278. "will be switched to using the body of ``self.run(*args, **kwargs)``.\n"
  279. "\n"
  280. "If the greenlet is active (has been run, but was switch()'ed\n"
  281. "out before leaving its run function), then this greenlet will\n"
  282. "be resumed and the return value to its switch call will be\n"
  283. "None if no arguments are given, the given argument if one\n"
  284. "argument is given, or the args tuple and keyword args dict if\n"
  285. "multiple arguments are given.\n"
  286. "\n"
  287. "If the greenlet is dead, or is the current greenlet then this\n"
  288. "function will simply return the arguments using the same rules as\n"
  289. "above.\n");
  290. static PyObject*
  291. green_switch(PyGreenlet* self, PyObject* args, PyObject* kwargs)
  292. {
  293. using greenlet::SwitchingArgs;
  294. SwitchingArgs switch_args(OwnedObject::owning(args), OwnedObject::owning(kwargs));
  295. self->pimpl->may_switch_away();
  296. self->pimpl->args() <<= switch_args;
  297. // If we're switching out of a greenlet, and that switch is the
  298. // last thing the greenlet does, the greenlet ought to be able to
  299. // go ahead and die at that point. Currently, someone else must
  300. // manually switch back to the greenlet so that we "fall off the
  301. // end" and can perform cleanup. You'd think we'd be able to
  302. // figure out that this is happening using the frame's ``f_lasti``
  303. // member, which is supposed to be an index into
  304. // ``frame->f_code->co_code``, the bytecode string. However, in
  305. // recent interpreters, ``f_lasti`` tends not to be updated thanks
  306. // to things like the PREDICT() macros in ceval.c. So it doesn't
  307. // really work to do that in many cases. For example, the Python
  308. // code:
  309. // def run():
  310. // greenlet.getcurrent().parent.switch()
  311. // produces bytecode of len 16, with the actual call to switch()
  312. // being at index 10 (in Python 3.10). However, the reported
  313. // ``f_lasti`` we actually see is...5! (Which happens to be the
  314. // second byte of the CALL_METHOD op for ``getcurrent()``).
  315. try {
  316. //OwnedObject result = single_result(self->pimpl->g_switch());
  317. OwnedObject result(single_result(self->pimpl->g_switch()));
  318. #ifndef NDEBUG
  319. // Note that the current greenlet isn't necessarily self. If self
  320. // finished, we went to one of its parents.
  321. assert(!self->pimpl->args());
  322. const BorrowedGreenlet& current = GET_THREAD_STATE().state().borrow_current();
  323. // It's possible it's never been switched to.
  324. assert(!current->args());
  325. #endif
  326. PyObject* p = result.relinquish_ownership();
  327. if (!p && !PyErr_Occurred()) {
  328. // This shouldn't be happening anymore, so the asserts
  329. // are there for debug builds. Non-debug builds
  330. // crash "gracefully" in this case, although there is an
  331. // argument to be made for killing the process in all
  332. // cases --- for this to be the case, our switches
  333. // probably nested in an incorrect way, so the state is
  334. // suspicious. Nothing should be corrupt though, just
  335. // confused at the Python level. Letting this propagate is
  336. // probably good enough.
  337. assert(p || PyErr_Occurred());
  338. throw PyErrOccurred(
  339. mod_globs->PyExc_GreenletError,
  340. "Greenlet.switch() returned NULL without an exception set."
  341. );
  342. }
  343. return p;
  344. }
  345. catch(const PyErrOccurred&) {
  346. return nullptr;
  347. }
  348. }
  349. PyDoc_STRVAR(
  350. green_throw_doc,
  351. "Switches execution to this greenlet, but immediately raises the\n"
  352. "given exception in this greenlet. If no argument is provided, the "
  353. "exception\n"
  354. "defaults to `greenlet.GreenletExit`. The normal exception\n"
  355. "propagation rules apply, as described for `switch`. Note that calling "
  356. "this\n"
  357. "method is almost equivalent to the following::\n"
  358. "\n"
  359. " def raiser():\n"
  360. " raise typ, val, tb\n"
  361. " g_raiser = greenlet(raiser, parent=g)\n"
  362. " g_raiser.switch()\n"
  363. "\n"
  364. "except that this trick does not work for the\n"
  365. "`greenlet.GreenletExit` exception, which would not propagate\n"
  366. "from ``g_raiser`` to ``g``.\n");
  367. static PyObject*
  368. green_throw(PyGreenlet* self, PyObject* args)
  369. {
  370. PyArgParseParam typ(mod_globs->PyExc_GreenletExit);
  371. PyArgParseParam val;
  372. PyArgParseParam tb;
  373. if (!PyArg_ParseTuple(args, "|OOO:throw", &typ, &val, &tb)) {
  374. return nullptr;
  375. }
  376. assert(typ.borrow() || val.borrow());
  377. self->pimpl->may_switch_away();
  378. try {
  379. // Both normalizing the error and the actual throw_greenlet
  380. // could throw PyErrOccurred.
  381. PyErrPieces err_pieces(typ.borrow(), val.borrow(), tb.borrow());
  382. return internal_green_throw(self, err_pieces).relinquish_ownership();
  383. }
  384. catch (const PyErrOccurred&) {
  385. return nullptr;
  386. }
  387. }
  388. static int
  389. green_bool(PyGreenlet* self)
  390. {
  391. return self->pimpl->active();
  392. }
  393. /**
  394. * CAUTION: Allocates memory, may run GC and arbitrary Python code.
  395. */
  396. static PyObject*
  397. green_getdict(PyGreenlet* self, void* UNUSED(context))
  398. {
  399. if (self->dict == NULL) {
  400. self->dict = PyDict_New();
  401. if (self->dict == NULL) {
  402. return NULL;
  403. }
  404. }
  405. Py_INCREF(self->dict);
  406. return self->dict;
  407. }
  408. static int
  409. green_setdict(PyGreenlet* self, PyObject* val, void* UNUSED(context))
  410. {
  411. PyObject* tmp;
  412. if (val == NULL) {
  413. PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted");
  414. return -1;
  415. }
  416. if (!PyDict_Check(val)) {
  417. PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary");
  418. return -1;
  419. }
  420. tmp = self->dict;
  421. Py_INCREF(val);
  422. self->dict = val;
  423. Py_XDECREF(tmp);
  424. return 0;
  425. }
  426. static bool
  427. _green_not_dead(BorrowedGreenlet self)
  428. {
  429. // XXX: Where else should we do this?
  430. // Probably on entry to most Python-facing functions?
  431. if (self->was_running_in_dead_thread()) {
  432. self->deactivate_and_free();
  433. return false;
  434. }
  435. return self->active() || !self->started();
  436. }
  437. static PyObject*
  438. green_getdead(PyGreenlet* self, void* UNUSED(context))
  439. {
  440. if (_green_not_dead(self)) {
  441. Py_RETURN_FALSE;
  442. }
  443. else {
  444. Py_RETURN_TRUE;
  445. }
  446. }
  447. static PyObject*
  448. green_get_stack_saved(PyGreenlet* self, void* UNUSED(context))
  449. {
  450. return PyLong_FromSsize_t(self->pimpl->stack_saved());
  451. }
  452. static PyObject*
  453. green_getrun(PyGreenlet* self, void* UNUSED(context))
  454. {
  455. try {
  456. OwnedObject result(BorrowedGreenlet(self)->run());
  457. return result.relinquish_ownership();
  458. }
  459. catch(const PyErrOccurred&) {
  460. return nullptr;
  461. }
  462. }
  463. static int
  464. green_setrun(PyGreenlet* self, PyObject* nrun, void* UNUSED(context))
  465. {
  466. try {
  467. BorrowedGreenlet(self)->run(nrun);
  468. return 0;
  469. }
  470. catch(const PyErrOccurred&) {
  471. return -1;
  472. }
  473. }
  474. static PyObject*
  475. green_getparent(PyGreenlet* self, void* UNUSED(context))
  476. {
  477. return BorrowedGreenlet(self)->parent().acquire_or_None();
  478. }
  479. static int
  480. green_setparent(PyGreenlet* self, PyObject* nparent, void* UNUSED(context))
  481. {
  482. try {
  483. BorrowedGreenlet(self)->parent(nparent);
  484. }
  485. catch(const PyErrOccurred&) {
  486. return -1;
  487. }
  488. return 0;
  489. }
  490. static PyObject*
  491. green_getcontext(const PyGreenlet* self, void* UNUSED(context))
  492. {
  493. const Greenlet *const g = self->pimpl;
  494. try {
  495. OwnedObject result(g->context());
  496. return result.relinquish_ownership();
  497. }
  498. catch(const PyErrOccurred&) {
  499. return nullptr;
  500. }
  501. }
  502. static int
  503. green_setcontext(PyGreenlet* self, PyObject* nctx, void* UNUSED(context))
  504. {
  505. try {
  506. BorrowedGreenlet(self)->context(nctx);
  507. return 0;
  508. }
  509. catch(const PyErrOccurred&) {
  510. return -1;
  511. }
  512. }
  513. static PyObject*
  514. green_getframe(PyGreenlet* self, void* UNUSED(context))
  515. {
  516. const PythonState::OwnedFrame& top_frame = BorrowedGreenlet(self)->top_frame();
  517. return top_frame.acquire_or_None();
  518. }
  519. static PyObject*
  520. green_getstate(PyGreenlet* self)
  521. {
  522. PyErr_Format(PyExc_TypeError,
  523. "cannot serialize '%s' object",
  524. Py_TYPE(self)->tp_name);
  525. return nullptr;
  526. }
  527. static PyObject*
  528. green_repr(PyGreenlet* _self)
  529. {
  530. BorrowedGreenlet self(_self);
  531. /*
  532. Return a string like
  533. <greenlet.greenlet at 0xdeadbeef [current][active started]|dead main>
  534. The handling of greenlets across threads is not super good.
  535. We mostly use the internal definitions of these terms, but they
  536. generally should make sense to users as well.
  537. */
  538. PyObject* result;
  539. int never_started = !self->started() && !self->active();
  540. const char* const tp_name = Py_TYPE(self)->tp_name;
  541. if (_green_not_dead(self)) {
  542. /* XXX: The otid= is almost useless because you can't correlate it to
  543. any thread identifier exposed to Python. We could use
  544. PyThreadState_GET()->thread_id, but we'd need to save that in the
  545. greenlet, or save the whole PyThreadState object itself.
  546. As it stands, its only useful for identifying greenlets from the same thread.
  547. */
  548. const char* state_in_thread;
  549. if (self->was_running_in_dead_thread()) {
  550. // The thread it was running in is dead!
  551. // This can happen, especially at interpreter shut down.
  552. // It complicates debugging output because it may be
  553. // impossible to access the current thread state at that
  554. // time. Thus, don't access the current thread state.
  555. state_in_thread = " (thread exited)";
  556. }
  557. else {
  558. state_in_thread = GET_THREAD_STATE().state().is_current(self)
  559. ? " current"
  560. : (self->started() ? " suspended" : "");
  561. }
  562. result = PyUnicode_FromFormat(
  563. "<%s object at %p (otid=%p)%s%s%s%s>",
  564. tp_name,
  565. self.borrow_o(),
  566. self->thread_state(),
  567. state_in_thread,
  568. self->active() ? " active" : "",
  569. never_started ? " pending" : " started",
  570. self->main() ? " main" : ""
  571. );
  572. }
  573. else {
  574. result = PyUnicode_FromFormat(
  575. "<%s object at %p (otid=%p) %sdead>",
  576. tp_name,
  577. self.borrow_o(),
  578. self->thread_state(),
  579. self->was_running_in_dead_thread()
  580. ? "(thread exited) "
  581. : ""
  582. );
  583. }
  584. return result;
  585. }
  586. static PyMethodDef green_methods[] = {
  587. {
  588. .ml_name="switch",
  589. .ml_meth=reinterpret_cast<PyCFunction>(green_switch),
  590. .ml_flags=METH_VARARGS | METH_KEYWORDS,
  591. .ml_doc=green_switch_doc
  592. },
  593. {.ml_name="throw", .ml_meth=(PyCFunction)green_throw, .ml_flags=METH_VARARGS, .ml_doc=green_throw_doc},
  594. {.ml_name="__getstate__", .ml_meth=(PyCFunction)green_getstate, .ml_flags=METH_NOARGS, .ml_doc=NULL},
  595. {.ml_name=NULL, .ml_meth=NULL} /* sentinel */
  596. };
  597. static PyGetSetDef green_getsets[] = {
  598. /* name, getter, setter, doc, context pointer */
  599. {.name="__dict__", .get=(getter)green_getdict, .set=(setter)green_setdict},
  600. {.name="run", .get=(getter)green_getrun, .set=(setter)green_setrun},
  601. {.name="parent", .get=(getter)green_getparent, .set=(setter)green_setparent},
  602. {.name="gr_frame", .get=(getter)green_getframe },
  603. {
  604. .name="gr_context",
  605. .get=(getter)green_getcontext,
  606. .set=(setter)green_setcontext
  607. },
  608. {.name="dead", .get=(getter)green_getdead},
  609. {.name="_stack_saved", .get=(getter)green_get_stack_saved},
  610. {.name=NULL}
  611. };
  612. static PyMemberDef green_members[] = {
  613. {.name=NULL}
  614. };
  615. static PyNumberMethods green_as_number = {
  616. .nb_bool=(inquiry)green_bool,
  617. };
  618. PyTypeObject PyGreenlet_Type = {
  619. .ob_base=PyVarObject_HEAD_INIT(NULL, 0)
  620. .tp_name="greenlet.greenlet", /* tp_name */
  621. .tp_basicsize=sizeof(PyGreenlet), /* tp_basicsize */
  622. /* methods */
  623. .tp_dealloc=(destructor)green_dealloc, /* tp_dealloc */
  624. .tp_repr=(reprfunc)green_repr, /* tp_repr */
  625. .tp_as_number=&green_as_number, /* tp_as _number*/
  626. .tp_flags=G_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  627. .tp_doc="greenlet(run=None, parent=None) -> greenlet\n\n"
  628. "Creates a new greenlet object (without running it).\n\n"
  629. " - *run* -- The callable to invoke.\n"
  630. " - *parent* -- The parent greenlet. The default is the current "
  631. "greenlet.", /* tp_doc */
  632. .tp_traverse=(traverseproc)green_traverse, /* tp_traverse */
  633. .tp_clear=(inquiry)green_clear, /* tp_clear */
  634. .tp_weaklistoffset=offsetof(PyGreenlet, weakreflist), /* tp_weaklistoffset */
  635. .tp_methods=green_methods, /* tp_methods */
  636. .tp_members=green_members, /* tp_members */
  637. .tp_getset=green_getsets, /* tp_getset */
  638. .tp_dictoffset=offsetof(PyGreenlet, dict), /* tp_dictoffset */
  639. .tp_init=(initproc)green_init, /* tp_init */
  640. .tp_alloc=PyType_GenericAlloc, /* tp_alloc */
  641. .tp_new=(newfunc)green_new, /* tp_new */
  642. .tp_free=PyObject_GC_Del, /* tp_free */
  643. .tp_is_gc=(inquiry)green_is_gc, /* tp_is_gc */
  644. };
  645. #endif
  646. // Local Variables:
  647. // flycheck-clang-include-path: ("/opt/local/Library/Frameworks/Python.framework/Versions/3.8/include/python3.8")
  648. // End: