TGreenlet.hpp 27 KB

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