Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

825 строки
28 KiB

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