TGreenlet.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. #ifndef GREENLET_GREENLET_HPP
  2. #define GREENLET_GREENLET_HPP
  3. /*
  4. * Declarations of the core data structures.
  5. */
  6. #define PY_SSIZE_T_CLEAN
  7. #include <Python.h>
  8. #include "greenlet_compiler_compat.hpp"
  9. #include "greenlet_refs.hpp"
  10. #include "greenlet_cpython_compat.hpp"
  11. #include "greenlet_allocator.hpp"
  12. using greenlet::refs::OwnedObject;
  13. using greenlet::refs::OwnedGreenlet;
  14. using greenlet::refs::OwnedMainGreenlet;
  15. using greenlet::refs::BorrowedGreenlet;
  16. #if PY_VERSION_HEX < 0x30B00A6
  17. # define _PyCFrame CFrame
  18. # define _PyInterpreterFrame _interpreter_frame
  19. #endif
  20. #if GREENLET_PY312
  21. # define Py_BUILD_CORE
  22. # include "internal/pycore_frame.h"
  23. #endif
  24. #if GREENLET_PY314
  25. # include "internal/pycore_interpframe_structs.h"
  26. #if defined(_MSC_VER) || defined(__MINGW64__)
  27. # include "greenlet_msvc_compat.hpp"
  28. #else
  29. # include "internal/pycore_interpframe.h"
  30. #endif
  31. #endif
  32. // XXX: TODO: Work to remove all virtual functions
  33. // for speed of calling and size of objects (no vtable).
  34. // One pattern is the Curiously Recurring Template
  35. namespace greenlet
  36. {
  37. class ExceptionState
  38. {
  39. private:
  40. G_NO_COPIES_OF_CLS(ExceptionState);
  41. // Even though these are borrowed objects, we actually own
  42. // them, when they're not null.
  43. // XXX: Express that in the API.
  44. private:
  45. _PyErr_StackItem* exc_info;
  46. _PyErr_StackItem exc_state;
  47. public:
  48. ExceptionState();
  49. void operator<<(const PyThreadState *const tstate) noexcept;
  50. void operator>>(PyThreadState* tstate) noexcept;
  51. void clear() noexcept;
  52. int tp_traverse(visitproc visit, void* arg) noexcept;
  53. void tp_clear() noexcept;
  54. };
  55. template<typename T>
  56. void operator<<(const PyThreadState *const tstate, T& exc);
  57. class PythonStateContext
  58. {
  59. protected:
  60. greenlet::refs::OwnedContext _context;
  61. public:
  62. inline const greenlet::refs::OwnedContext& context() const
  63. {
  64. return this->_context;
  65. }
  66. inline greenlet::refs::OwnedContext& context()
  67. {
  68. return this->_context;
  69. }
  70. inline void tp_clear()
  71. {
  72. this->_context.CLEAR();
  73. }
  74. template<typename T>
  75. inline static PyObject* context(T* tstate)
  76. {
  77. return tstate->context;
  78. }
  79. template<typename T>
  80. inline static void context(T* tstate, PyObject* new_context)
  81. {
  82. tstate->context = new_context;
  83. tstate->context_ver++;
  84. }
  85. };
  86. class SwitchingArgs;
  87. class PythonState : public PythonStateContext
  88. {
  89. public:
  90. typedef greenlet::refs::OwnedReference<struct _frame> OwnedFrame;
  91. private:
  92. G_NO_COPIES_OF_CLS(PythonState);
  93. // We own this if we're suspended (although currently we don't
  94. // tp_traverse into it; that's a TODO). If we're running, it's
  95. // empty. If we get deallocated and *still* have a frame, it
  96. // won't be reachable from the place that normally decref's
  97. // it, so we need to do it (hence owning it).
  98. OwnedFrame _top_frame;
  99. #if GREENLET_USE_CFRAME
  100. _PyCFrame* cframe;
  101. int use_tracing;
  102. #endif
  103. #if GREENLET_PY314
  104. int py_recursion_depth;
  105. // I think this is only used by the JIT. At least,
  106. // we only got errors not switching it when the JIT was enabled.
  107. // Python/generated_cases.c.h:12469: _PyEval_EvalFrameDefault:
  108. // Assertion `tstate->current_executor == NULL' failed.
  109. // see https://github.com/python-greenlet/greenlet/issues/460
  110. PyObject* current_executor;
  111. #elif GREENLET_PY312
  112. int py_recursion_depth;
  113. int c_recursion_depth;
  114. #else
  115. int recursion_depth;
  116. #endif
  117. #if GREENLET_PY313
  118. PyObject *delete_later;
  119. #else
  120. int trash_delete_nesting;
  121. #endif
  122. #if GREENLET_PY311
  123. _PyInterpreterFrame* current_frame;
  124. _PyStackChunk* datastack_chunk;
  125. PyObject** datastack_top;
  126. PyObject** datastack_limit;
  127. #endif
  128. // The PyInterpreterFrame list on 3.12+ contains some entries that are
  129. // on the C stack, which can't be directly accessed while a greenlet is
  130. // suspended. In order to keep greenlet gr_frame introspection working,
  131. // we adjust stack switching to rewrite the interpreter frame list
  132. // to skip these C-stack frames; we call this "exposing" the greenlet's
  133. // frames because it makes them valid to work with in Python. Then when
  134. // the greenlet is resumed we need to remember to reverse the operation
  135. // we did. The C-stack frames are "entry frames" which are a low-level
  136. // interpreter detail; they're not needed for introspection, but do
  137. // need to be present for the eval loop to work.
  138. void unexpose_frames();
  139. public:
  140. PythonState();
  141. // You can use this for testing whether we have a frame
  142. // or not. It returns const so they can't modify it.
  143. const OwnedFrame& top_frame() const noexcept;
  144. inline void operator<<(const PyThreadState *const tstate) noexcept;
  145. inline void operator>>(PyThreadState* tstate) noexcept;
  146. void clear() noexcept;
  147. int tp_traverse(visitproc visit, void* arg, bool visit_top_frame) noexcept;
  148. void tp_clear(bool own_top_frame) noexcept;
  149. void set_initial_state(const PyThreadState* const tstate) noexcept;
  150. #if GREENLET_USE_CFRAME
  151. void set_new_cframe(_PyCFrame& frame) noexcept;
  152. #endif
  153. void may_switch_away() noexcept;
  154. inline void will_switch_from(PyThreadState *const origin_tstate) noexcept;
  155. void did_finish(PyThreadState* tstate) noexcept;
  156. };
  157. class StackState
  158. {
  159. // By having only plain C (POD) members, no virtual functions
  160. // or bases, we get a trivial assignment operator generated
  161. // for us. However, that's not safe since we do manage memory.
  162. // So we declare an assignment operator that only works if we
  163. // don't have any memory allocated. (We don't use
  164. // std::shared_ptr for reference counting just to keep this
  165. // object small)
  166. private:
  167. char* _stack_start;
  168. char* stack_stop;
  169. char* stack_copy;
  170. intptr_t _stack_saved;
  171. StackState* stack_prev;
  172. inline int copy_stack_to_heap_up_to(const char* const stop) noexcept;
  173. inline void free_stack_copy() noexcept;
  174. public:
  175. /**
  176. * Creates a started, but inactive, state, using *current*
  177. * as the previous.
  178. */
  179. StackState(void* mark, StackState& current);
  180. /**
  181. * Creates an inactive, unstarted, state.
  182. */
  183. StackState();
  184. ~StackState();
  185. StackState(const StackState& other);
  186. StackState& operator=(const StackState& other);
  187. inline void copy_heap_to_stack(const StackState& current) noexcept;
  188. inline int copy_stack_to_heap(char* const stackref, const StackState& current) noexcept;
  189. inline bool started() const noexcept;
  190. inline bool main() const noexcept;
  191. inline bool active() const noexcept;
  192. inline void set_active() noexcept;
  193. inline void set_inactive() noexcept;
  194. inline intptr_t stack_saved() const noexcept;
  195. inline char* stack_start() const noexcept;
  196. static inline StackState make_main() noexcept;
  197. #ifdef GREENLET_USE_STDIO
  198. friend std::ostream& operator<<(std::ostream& os, const StackState& s);
  199. #endif
  200. // Fill in [dest, dest + n) with the values that would be at
  201. // [src, src + n) while this greenlet is running. This is like memcpy
  202. // except that if the greenlet is suspended it accounts for the portion
  203. // of the greenlet's stack that was spilled to the heap. `src` may
  204. // be on this greenlet's stack, or on the heap, but not on a different
  205. // greenlet's stack.
  206. void copy_from_stack(void* dest, const void* src, size_t n) const;
  207. };
  208. #ifdef GREENLET_USE_STDIO
  209. std::ostream& operator<<(std::ostream& os, const StackState& s);
  210. #endif
  211. class SwitchingArgs
  212. {
  213. private:
  214. G_NO_ASSIGNMENT_OF_CLS(SwitchingArgs);
  215. // If args and kwargs are both false (NULL), this is a *throw*, not a
  216. // switch. PyErr_... must have been called already.
  217. OwnedObject _args;
  218. OwnedObject _kwargs;
  219. public:
  220. SwitchingArgs()
  221. {}
  222. SwitchingArgs(const OwnedObject& args, const OwnedObject& kwargs)
  223. : _args(args),
  224. _kwargs(kwargs)
  225. {}
  226. SwitchingArgs(const SwitchingArgs& other)
  227. : _args(other._args),
  228. _kwargs(other._kwargs)
  229. {}
  230. const OwnedObject& args()
  231. {
  232. return this->_args;
  233. }
  234. const OwnedObject& kwargs()
  235. {
  236. return this->_kwargs;
  237. }
  238. /**
  239. * Moves ownership from the argument to this object.
  240. */
  241. SwitchingArgs& operator<<=(SwitchingArgs& other)
  242. {
  243. if (this != &other) {
  244. this->_args = other._args;
  245. this->_kwargs = other._kwargs;
  246. other.CLEAR();
  247. }
  248. return *this;
  249. }
  250. /**
  251. * Acquires ownership of the argument (consumes the reference).
  252. */
  253. SwitchingArgs& operator<<=(PyObject* args)
  254. {
  255. this->_args = OwnedObject::consuming(args);
  256. this->_kwargs.CLEAR();
  257. return *this;
  258. }
  259. /**
  260. * Acquires ownership of the argument.
  261. *
  262. * Sets the args to be the given value; clears the kwargs.
  263. */
  264. SwitchingArgs& operator<<=(OwnedObject& args)
  265. {
  266. assert(&args != &this->_args);
  267. this->_args = args;
  268. this->_kwargs.CLEAR();
  269. args.CLEAR();
  270. return *this;
  271. }
  272. explicit operator bool() const noexcept
  273. {
  274. return this->_args || this->_kwargs;
  275. }
  276. inline void CLEAR()
  277. {
  278. this->_args.CLEAR();
  279. this->_kwargs.CLEAR();
  280. }
  281. const std::string as_str() const noexcept
  282. {
  283. return PyUnicode_AsUTF8(
  284. OwnedObject::consuming(
  285. PyUnicode_FromFormat(
  286. "SwitchingArgs(args=%R, kwargs=%R)",
  287. this->_args.borrow(),
  288. this->_kwargs.borrow()
  289. )
  290. ).borrow()
  291. );
  292. }
  293. };
  294. class ThreadState;
  295. class UserGreenlet;
  296. class MainGreenlet;
  297. class Greenlet
  298. {
  299. private:
  300. G_NO_COPIES_OF_CLS(Greenlet);
  301. PyGreenlet* const _self;
  302. private:
  303. // XXX: Work to remove these.
  304. friend class ThreadState;
  305. friend class UserGreenlet;
  306. friend class MainGreenlet;
  307. protected:
  308. ExceptionState exception_state;
  309. SwitchingArgs switch_args;
  310. StackState stack_state;
  311. PythonState python_state;
  312. Greenlet(PyGreenlet* p, const StackState& initial_state);
  313. public:
  314. // This constructor takes ownership of the PyGreenlet, by
  315. // setting ``p->pimpl = this;``.
  316. Greenlet(PyGreenlet* p);
  317. virtual ~Greenlet();
  318. const OwnedObject context() const;
  319. // You MUST call this _very_ early in the switching process to
  320. // prepare anything that may need prepared. This might perform
  321. // garbage collections or otherwise run arbitrary Python code.
  322. //
  323. // One specific use of it is for Python 3.11+, preventing
  324. // running arbitrary code at unsafe times. See
  325. // PythonState::may_switch_away().
  326. inline void may_switch_away()
  327. {
  328. this->python_state.may_switch_away();
  329. }
  330. inline void context(refs::BorrowedObject new_context);
  331. inline SwitchingArgs& args()
  332. {
  333. return this->switch_args;
  334. }
  335. virtual const refs::BorrowedMainGreenlet main_greenlet() const = 0;
  336. inline intptr_t stack_saved() const noexcept
  337. {
  338. return this->stack_state.stack_saved();
  339. }
  340. // This is used by the macro SLP_SAVE_STATE to compute the
  341. // difference in stack sizes. It might be nice to handle the
  342. // computation ourself, but the type of the result
  343. // varies by platform, so doing it in the macro is the
  344. // simplest way.
  345. inline const char* stack_start() const noexcept
  346. {
  347. return this->stack_state.stack_start();
  348. }
  349. virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state);
  350. virtual OwnedObject g_switch() = 0;
  351. /**
  352. * Force the greenlet to appear dead. Used when it's not
  353. * possible to throw an exception into a greenlet anymore.
  354. *
  355. * This losses access to the thread state and the main greenlet.
  356. */
  357. virtual void murder_in_place();
  358. /**
  359. * Called when somebody notices we were running in a dead
  360. * thread to allow cleaning up resources (because we can't
  361. * raise GreenletExit into it anymore).
  362. * This is very similar to ``murder_in_place()``, except that
  363. * it DOES NOT lose the main greenlet or thread state.
  364. */
  365. inline void deactivate_and_free();
  366. // Called when some thread wants to deallocate a greenlet
  367. // object.
  368. // The thread may or may not be the same thread the greenlet
  369. // was running in.
  370. // The thread state will be null if the thread the greenlet
  371. // was running in was known to have exited.
  372. void deallocing_greenlet_in_thread(const ThreadState* current_state);
  373. // Must be called on 3.12+ before exposing a suspended greenlet's
  374. // frames to user code. This rewrites the linked list of interpreter
  375. // frames to skip the ones that are being stored on the C stack (which
  376. // can't be safely accessed while the greenlet is suspended because
  377. // that stack space might be hosting a different greenlet), and
  378. // sets PythonState::frames_were_exposed so we remember to restore
  379. // the original list before resuming the greenlet. The C-stack frames
  380. // are a low-level interpreter implementation detail; while they're
  381. // important to the bytecode eval loop, they're superfluous for
  382. // introspection purposes.
  383. void expose_frames();
  384. // TODO: Figure out how to make these non-public.
  385. inline void slp_restore_state() noexcept;
  386. inline int slp_save_state(char *const stackref) noexcept;
  387. inline bool is_currently_running_in_some_thread() const;
  388. virtual bool belongs_to_thread(const ThreadState* state) const;
  389. inline bool started() const
  390. {
  391. return this->stack_state.started();
  392. }
  393. inline bool active() const
  394. {
  395. return this->stack_state.active();
  396. }
  397. inline bool main() const
  398. {
  399. return this->stack_state.main();
  400. }
  401. virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const = 0;
  402. virtual const OwnedGreenlet parent() const = 0;
  403. virtual void parent(const refs::BorrowedObject new_parent) = 0;
  404. inline const PythonState::OwnedFrame& top_frame()
  405. {
  406. return this->python_state.top_frame();
  407. }
  408. virtual const OwnedObject& run() const = 0;
  409. virtual void run(const refs::BorrowedObject nrun) = 0;
  410. virtual int tp_traverse(visitproc visit, void* arg);
  411. virtual int tp_clear();
  412. // Return the thread state that the greenlet is running in, or
  413. // null if the greenlet is not running or the thread is known
  414. // to have exited.
  415. virtual ThreadState* thread_state() const noexcept = 0;
  416. // Return true if the greenlet is known to have been running
  417. // (active) in a thread that has now exited.
  418. virtual bool was_running_in_dead_thread() const noexcept = 0;
  419. // Return a borrowed greenlet that is the Python object
  420. // this object represents.
  421. inline BorrowedGreenlet self() const noexcept
  422. {
  423. return BorrowedGreenlet(this->_self);
  424. }
  425. // For testing. If this returns true, we should pretend that
  426. // slp_switch() failed.
  427. virtual bool force_slp_switch_error() const noexcept;
  428. protected:
  429. inline void release_args();
  430. // The functions that must not be inlined are declared virtual.
  431. // We also mark them as protected, not private, so that the
  432. // compiler is forced to call them through a function pointer.
  433. // (A sufficiently smart compiler could directly call a private
  434. // virtual function since it can never be overridden in a
  435. // subclass).
  436. // Also TODO: Switch away from integer error codes and to enums,
  437. // or throw exceptions when possible.
  438. struct switchstack_result_t
  439. {
  440. int status;
  441. Greenlet* the_new_current_greenlet;
  442. OwnedGreenlet origin_greenlet;
  443. switchstack_result_t()
  444. : status(0),
  445. the_new_current_greenlet(nullptr)
  446. {}
  447. switchstack_result_t(int err)
  448. : status(err),
  449. the_new_current_greenlet(nullptr)
  450. {}
  451. switchstack_result_t(int err, Greenlet* state, OwnedGreenlet& origin)
  452. : status(err),
  453. the_new_current_greenlet(state),
  454. origin_greenlet(origin)
  455. {
  456. }
  457. switchstack_result_t(int err, Greenlet* state, const BorrowedGreenlet& origin)
  458. : status(err),
  459. the_new_current_greenlet(state),
  460. origin_greenlet(origin)
  461. {
  462. }
  463. switchstack_result_t(const switchstack_result_t& other)
  464. : status(other.status),
  465. the_new_current_greenlet(other.the_new_current_greenlet),
  466. origin_greenlet(other.origin_greenlet)
  467. {}
  468. switchstack_result_t& operator=(const switchstack_result_t& other)
  469. {
  470. this->status = other.status;
  471. this->the_new_current_greenlet = other.the_new_current_greenlet;
  472. this->origin_greenlet = other.origin_greenlet;
  473. return *this;
  474. }
  475. };
  476. OwnedObject on_switchstack_or_initialstub_failure(
  477. Greenlet* target,
  478. const switchstack_result_t& err,
  479. const bool target_was_me=false,
  480. const bool was_initial_stub=false);
  481. // Returns the previous greenlet we just switched away from.
  482. virtual OwnedGreenlet g_switchstack_success() noexcept;
  483. // Check the preconditions for switching to this greenlet; if they
  484. // aren't met, throws PyErrOccurred. Most callers will want to
  485. // catch this and clear the arguments
  486. inline void check_switch_allowed() const;
  487. class GreenletStartedWhileInPython : public std::runtime_error
  488. {
  489. public:
  490. GreenletStartedWhileInPython() : std::runtime_error("")
  491. {}
  492. };
  493. protected:
  494. /**
  495. Perform a stack switch into this greenlet.
  496. This temporarily sets the global variable
  497. ``switching_thread_state`` to this greenlet; as soon as the
  498. call to ``slp_switch`` completes, this is reset to NULL.
  499. Consequently, this depends on the GIL.
  500. TODO: Adopt the stackman model and pass ``slp_switch`` a
  501. callback function and context pointer; this eliminates the
  502. need for global variables altogether.
  503. Because the stack switch happens in this function, this
  504. function can't use its own stack (local) variables, set
  505. before the switch, and then accessed after the switch.
  506. Further, you con't even access ``g_thread_state_global``
  507. before and after the switch from the global variable.
  508. Because it is thread local some compilers cache it in a
  509. register/on the stack, notably new versions of MSVC; this
  510. breaks with strange crashes sometime later, because writing
  511. to anything in ``g_thread_state_global`` after the switch
  512. is actually writing to random memory. For this reason, we
  513. call a non-inlined function to finish the operation. (XXX:
  514. The ``/GT`` MSVC compiler argument probably fixes that.)
  515. It is very important that stack switch is 'atomic', i.e. no
  516. calls into other Python code allowed (except very few that
  517. are safe), because global variables are very fragile. (This
  518. should no longer be the case with thread-local variables.)
  519. */
  520. // Made virtual to facilitate subclassing UserGreenlet for testing.
  521. virtual switchstack_result_t g_switchstack(void);
  522. class TracingGuard
  523. {
  524. private:
  525. PyThreadState* tstate;
  526. public:
  527. TracingGuard()
  528. : tstate(PyThreadState_GET())
  529. {
  530. PyThreadState_EnterTracing(this->tstate);
  531. }
  532. ~TracingGuard()
  533. {
  534. PyThreadState_LeaveTracing(this->tstate);
  535. this->tstate = nullptr;
  536. }
  537. inline void CallTraceFunction(const OwnedObject& tracefunc,
  538. const greenlet::refs::ImmortalEventName& event,
  539. const BorrowedGreenlet& origin,
  540. const BorrowedGreenlet& target)
  541. {
  542. // TODO: This calls tracefunc(event, (origin, target)). Add a shortcut
  543. // function for that that's specialized to avoid the Py_BuildValue
  544. // string parsing, or start with just using "ON" format with PyTuple_Pack(2,
  545. // origin, target). That seems like what the N format is meant
  546. // for.
  547. // XXX: Why does event not automatically cast back to a PyObject?
  548. // It tries to call the "deleted constructor ImmortalEventName
  549. // const" instead.
  550. assert(tracefunc);
  551. assert(event);
  552. assert(origin);
  553. assert(target);
  554. greenlet::refs::NewReference retval(
  555. PyObject_CallFunction(
  556. tracefunc.borrow(),
  557. "O(OO)",
  558. event.borrow(),
  559. origin.borrow(),
  560. target.borrow()
  561. ));
  562. if (!retval) {
  563. throw PyErrOccurred::from_current();
  564. }
  565. }
  566. };
  567. static void
  568. g_calltrace(const OwnedObject& tracefunc,
  569. const greenlet::refs::ImmortalEventName& event,
  570. const greenlet::refs::BorrowedGreenlet& origin,
  571. const BorrowedGreenlet& target);
  572. private:
  573. OwnedObject g_switch_finish(const switchstack_result_t& err);
  574. };
  575. class UserGreenlet : public Greenlet
  576. {
  577. private:
  578. static greenlet::PythonAllocator<UserGreenlet> allocator;
  579. OwnedMainGreenlet _main_greenlet;
  580. OwnedObject _run_callable;
  581. OwnedGreenlet _parent;
  582. public:
  583. static void* operator new(size_t UNUSED(count));
  584. static void operator delete(void* ptr);
  585. UserGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent);
  586. virtual ~UserGreenlet();
  587. virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const;
  588. virtual bool was_running_in_dead_thread() const noexcept;
  589. virtual ThreadState* thread_state() const noexcept;
  590. virtual OwnedObject g_switch();
  591. virtual const OwnedObject& run() const
  592. {
  593. if (this->started() || !this->_run_callable) {
  594. throw AttributeError("run");
  595. }
  596. return this->_run_callable;
  597. }
  598. virtual void run(const refs::BorrowedObject nrun);
  599. virtual const OwnedGreenlet parent() const;
  600. virtual void parent(const refs::BorrowedObject new_parent);
  601. virtual const refs::BorrowedMainGreenlet main_greenlet() const;
  602. virtual void murder_in_place();
  603. virtual bool belongs_to_thread(const ThreadState* state) const;
  604. virtual int tp_traverse(visitproc visit, void* arg);
  605. virtual int tp_clear();
  606. class ParentIsCurrentGuard
  607. {
  608. private:
  609. OwnedGreenlet oldparent;
  610. UserGreenlet* greenlet;
  611. G_NO_COPIES_OF_CLS(ParentIsCurrentGuard);
  612. public:
  613. ParentIsCurrentGuard(UserGreenlet* p, const ThreadState& thread_state);
  614. ~ParentIsCurrentGuard();
  615. };
  616. virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state);
  617. protected:
  618. virtual switchstack_result_t g_initialstub(void* mark);
  619. private:
  620. // This function isn't meant to return.
  621. // This accepts raw pointers and the ownership of them at the
  622. // same time. The caller should use ``inner_bootstrap(origin.relinquish_ownership())``.
  623. void inner_bootstrap(PyGreenlet* origin_greenlet, PyObject* run);
  624. };
  625. class BrokenGreenlet : public UserGreenlet
  626. {
  627. private:
  628. static greenlet::PythonAllocator<BrokenGreenlet> allocator;
  629. public:
  630. bool _force_switch_error = false;
  631. bool _force_slp_switch_error = false;
  632. static void* operator new(size_t UNUSED(count));
  633. static void operator delete(void* ptr);
  634. BrokenGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent)
  635. : UserGreenlet(p, the_parent)
  636. {}
  637. virtual ~BrokenGreenlet()
  638. {}
  639. virtual switchstack_result_t g_switchstack(void);
  640. virtual bool force_slp_switch_error() const noexcept;
  641. };
  642. class MainGreenlet : public Greenlet
  643. {
  644. private:
  645. static greenlet::PythonAllocator<MainGreenlet> allocator;
  646. refs::BorrowedMainGreenlet _self;
  647. ThreadState* _thread_state;
  648. G_NO_COPIES_OF_CLS(MainGreenlet);
  649. public:
  650. static void* operator new(size_t UNUSED(count));
  651. static void operator delete(void* ptr);
  652. MainGreenlet(refs::BorrowedMainGreenlet::PyType*, ThreadState*);
  653. virtual ~MainGreenlet();
  654. virtual const OwnedObject& run() const;
  655. virtual void run(const refs::BorrowedObject nrun);
  656. virtual const OwnedGreenlet parent() const;
  657. virtual void parent(const refs::BorrowedObject new_parent);
  658. virtual const refs::BorrowedMainGreenlet main_greenlet() const;
  659. virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const;
  660. virtual bool was_running_in_dead_thread() const noexcept;
  661. virtual ThreadState* thread_state() const noexcept;
  662. void thread_state(ThreadState*) noexcept;
  663. virtual OwnedObject g_switch();
  664. virtual int tp_traverse(visitproc visit, void* arg);
  665. };
  666. // Instantiate one on the stack to save the GC state,
  667. // and then disable GC. When it goes out of scope, GC will be
  668. // restored to its original state. Sadly, these APIs are only
  669. // available on 3.10+; luckily, we only need them on 3.11+.
  670. #if GREENLET_PY310
  671. class GCDisabledGuard
  672. {
  673. private:
  674. int was_enabled = 0;
  675. public:
  676. GCDisabledGuard()
  677. : was_enabled(PyGC_IsEnabled())
  678. {
  679. PyGC_Disable();
  680. }
  681. ~GCDisabledGuard()
  682. {
  683. if (this->was_enabled) {
  684. PyGC_Enable();
  685. }
  686. }
  687. };
  688. #endif
  689. OwnedObject& operator<<=(OwnedObject& lhs, greenlet::SwitchingArgs& rhs) noexcept;
  690. //TODO: Greenlet::g_switch() should call this automatically on its
  691. //return value. As it is, the module code is calling it.
  692. static inline OwnedObject
  693. single_result(const OwnedObject& results)
  694. {
  695. if (results
  696. && PyTuple_Check(results.borrow())
  697. && PyTuple_GET_SIZE(results.borrow()) == 1) {
  698. PyObject* result = PyTuple_GET_ITEM(results.borrow(), 0);
  699. assert(result);
  700. return OwnedObject::owning(result);
  701. }
  702. return results;
  703. }
  704. static OwnedObject
  705. g_handle_exit(const OwnedObject& greenlet_result);
  706. template<typename T>
  707. void operator<<(const PyThreadState *const lhs, T& rhs)
  708. {
  709. rhs.operator<<(lhs);
  710. }
  711. } // namespace greenlet ;
  712. #endif