PyGreenlet.cpp 24 KB

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