1#ifndef GREENLET_GREENLET_HPP
2#define GREENLET_GREENLET_HPP
7#define PY_SSIZE_T_CLEAN
10#include "greenlet_compiler_compat.hpp"
11#include "greenlet_refs.hpp"
12#include "greenlet_cpython_compat.hpp"
13#include "greenlet_allocator.hpp"
20#if PY_VERSION_HEX < 0x30B00A6
21# define _PyCFrame CFrame
22# define _PyInterpreterFrame _interpreter_frame
27# include "internal/pycore_frame.h"
31# include "internal/pycore_interpframe_structs.h"
32#if defined(_MSC_VER) || defined(__MINGW64__)
33# include "greenlet_msvc_compat.hpp"
35# include "internal/pycore_interpframe.h"
38# include "internal/pycore_tstate.h"
56 _PyErr_StackItem* exc_info;
57 _PyErr_StackItem exc_state;
60 void operator<<(
const PyThreadState *
const tstate)
noexcept;
61 void operator>>(PyThreadState* tstate)
noexcept;
62 void clear()
noexcept;
64 int tp_traverse(visitproc visit,
void* arg)
noexcept;
65 void tp_clear()
noexcept;
69 void operator<<(
const PyThreadState *
const tstate, T& exc);
78 return this->_context;
82 return this->_context;
85 inline void tp_clear()
87 this->_context.CLEAR();
91 inline static PyObject* context(T* tstate)
93 return tstate->context;
97 inline static void context(T* tstate, PyObject* new_context)
99 tstate->context = new_context;
100 tstate->context_ver++;
116#if GREENLET_USE_CFRAME
121 int py_recursion_depth;
127 PyObject* current_executor;
128 _PyStackRef* stackpointer;
129 #ifdef Py_GIL_DISABLED
130 _PyCStackRef* c_stack_refs;
133 int py_recursion_depth;
134 int c_recursion_depth;
139 PyObject *delete_later;
141 int trash_delete_nesting;
144 _PyInterpreterFrame* current_frame;
145 _PyStackChunk* datastack_chunk;
146 PyObject** datastack_top;
147 PyObject** datastack_limit;
159 void unexpose_frames();
168 inline void operator<<(
const PyThreadState *
const tstate)
noexcept;
169 inline void operator>>(PyThreadState* tstate)
noexcept;
170 void clear()
noexcept;
172 int tp_traverse(visitproc visit,
void* arg,
bool visit_top_frame)
noexcept;
173 void tp_clear(
bool own_top_frame)
noexcept;
174 void set_initial_state(
const PyThreadState*
const tstate)
noexcept;
175#if GREENLET_USE_CFRAME
176 void set_new_cframe(_PyCFrame& frame)
noexcept;
179 void may_switch_away()
noexcept;
180 inline void will_switch_from(PyThreadState *
const origin_tstate)
noexcept;
181 void did_finish(PyThreadState* tstate)
noexcept;
197 intptr_t _stack_saved;
199 inline int copy_stack_to_heap_up_to(
const char*
const stop)
noexcept;
200 inline void free_stack_copy()
noexcept;
215 inline void copy_heap_to_stack(
const StackState& current)
noexcept;
216 inline int copy_stack_to_heap(
char*
const stackref,
const StackState& current)
noexcept;
217 inline bool started()
const noexcept;
218 inline bool main()
const noexcept;
219 inline bool active()
const noexcept;
220 inline void set_active()
noexcept;
221 inline void set_inactive()
noexcept;
222 inline intptr_t stack_saved()
const noexcept;
223 inline char* stack_start()
const noexcept;
224 static inline StackState make_main()
noexcept;
225#ifdef GREENLET_USE_STDIO
226 friend std::ostream& operator<<(std::ostream& os,
const StackState& s);
235 void copy_from_stack(
void* dest,
const void* src,
size_t n)
const;
237#ifdef GREENLET_USE_STDIO
238 std::ostream& operator<<(std::ostream& os,
const StackState& s);
254 SwitchingArgs(
const OwnedObject& args,
const OwnedObject& kwargs)
260 : _args(other._args),
261 _kwargs(other._kwargs)
264 const OwnedObject& args()
269 const OwnedObject& kwargs()
271 return this->_kwargs;
279 if (
this != &other) {
280 this->_args = other._args;
281 this->_kwargs = other._kwargs;
292 this->_args = OwnedObject::consuming(args);
293 this->_kwargs.CLEAR();
304 assert(&args != &this->_args);
306 this->_kwargs.CLEAR();
312 explicit operator bool() const noexcept
314 return this->_args || this->_kwargs;
320 this->_kwargs.CLEAR();
323 const std::string as_str() const noexcept
325 return PyUnicode_AsUTF8(
326 OwnedObject::consuming(
327 PyUnicode_FromFormat(
328 "SwitchingArgs(args=%R, kwargs=%R)",
329 this->_args.borrow(),
330 this->_kwargs.borrow()
364 const OwnedObject context()
const;
373 inline void may_switch_away()
375 this->python_state.may_switch_away();
382 return this->switch_args;
387 inline intptr_t stack_saved()
const noexcept
389 return this->stack_state.stack_saved();
397 inline const char* stack_start()
const noexcept
399 return this->stack_state.stack_start();
403 virtual OwnedObject g_switch() = 0;
428 void deallocing_greenlet_in_thread(
const ThreadState* current_state);
440 void expose_frames();
444 inline void slp_restore_state()
noexcept;
445 inline int slp_save_state(
char *
const stackref)
noexcept;
447 inline bool is_currently_running_in_some_thread()
const;
448 virtual bool belongs_to_thread(
const ThreadState* state)
const;
450 inline bool started()
const
452 return this->stack_state.started();
454 inline bool active()
const
456 return this->stack_state.active();
458 inline bool main()
const
460 return this->stack_state.main();
464 virtual const OwnedGreenlet parent()
const = 0;
469 return this->python_state.top_frame();
472 virtual const OwnedObject& run()
const = 0;
476 virtual int tp_traverse(visitproc visit,
void* arg);
477 virtual int tp_clear();
483 virtual ThreadState* thread_state()
const noexcept = 0;
487 virtual bool was_running_in_dead_thread()
const noexcept = 0;
491 inline BorrowedGreenlet self()
const noexcept
493 return BorrowedGreenlet(this->_self);
498 virtual bool force_slp_switch_error()
const noexcept;
501 inline void release_args();
516 OwnedGreenlet origin_greenlet;
520 the_new_current_greenlet(
nullptr)
525 the_new_current_greenlet(
nullptr)
530 the_new_current_greenlet(state),
531 origin_greenlet(origin)
537 the_new_current_greenlet(state),
538 origin_greenlet(origin)
543 : status(other.status),
544 the_new_current_greenlet(other.the_new_current_greenlet),
545 origin_greenlet(other.origin_greenlet)
550 this->status = other.status;
551 this->the_new_current_greenlet = other.the_new_current_greenlet;
552 this->origin_greenlet = other.origin_greenlet;
560 const bool target_was_me=
false,
561 const bool was_initial_stub=
false);
564 virtual OwnedGreenlet g_switchstack_success() noexcept;
570 inline
void check_switch_allowed() const;
619 PyThreadState* tstate;
622 : tstate(PyThreadState_GET())
624 PyThreadState_EnterTracing(this->tstate);
629 PyThreadState_LeaveTracing(this->tstate);
630 this->tstate =
nullptr;
633 inline void CallTraceFunction(
const OwnedObject& tracefunc,
635 const BorrowedGreenlet& origin,
636 const BorrowedGreenlet& target)
651 PyObject_CallFunction(
659 throw PyErrOccurred::from_current();
665 g_calltrace(
const OwnedObject& tracefunc,
668 const BorrowedGreenlet& target);
678 OwnedMainGreenlet _main_greenlet;
679 OwnedObject _run_callable;
680 OwnedGreenlet _parent;
682 static void*
operator new(
size_t UNUSED(count));
683 static void operator delete(
void* ptr);
689 virtual bool was_running_in_dead_thread()
const noexcept;
690 virtual ThreadState* thread_state()
const noexcept;
691 virtual OwnedObject g_switch();
692 virtual const OwnedObject& run()
const
694 if (this->started() || !this->_run_callable) {
697 return this->_run_callable;
701 virtual const OwnedGreenlet parent()
const;
707 virtual bool belongs_to_thread(
const ThreadState* state)
const;
708 virtual int tp_traverse(visitproc visit,
void* arg);
709 virtual int tp_clear();
713 OwnedGreenlet oldparent;
727 void inner_bootstrap(
PyGreenlet* origin_greenlet, PyObject* run);
735 bool _force_switch_error =
false;
736 bool _force_slp_switch_error =
false;
738 static void*
operator new(
size_t UNUSED(count));
739 static void operator delete(
void* ptr);
747 virtual bool force_slp_switch_error()
const noexcept;
759 static void*
operator new(
size_t UNUSED(count));
760 static void operator delete(
void* ptr);
766 virtual const OwnedObject& run()
const;
769 virtual const OwnedGreenlet parent()
const;
775 virtual bool was_running_in_dead_thread()
const noexcept;
776 virtual ThreadState* thread_state()
const noexcept;
778 virtual OwnedObject g_switch();
779 virtual int tp_traverse(visitproc visit,
void* arg);
787 class GCDisabledGuard
793 : was_enabled(PyGC_IsEnabled())
800 if (this->was_enabled) {
811 static inline OwnedObject
812 single_result(
const OwnedObject& results)
815 && PyTuple_Check(results.borrow())
816 && PyTuple_GET_SIZE(results.borrow()) == 1) {
817 PyObject* result = PyTuple_GET_ITEM(results.borrow(), 0);
819 return OwnedObject::owning(result);
826 g_handle_exit(
const OwnedObject& greenlet_result);
830 void operator<<(
const PyThreadState *
const lhs, T& rhs)
Definition greenlet_exceptions.hpp:126
Definition TGreenlet.hpp:731
virtual switchstack_result_t g_switchstack(void)
Definition TBrokenGreenlet.cpp:37
Definition TGreenlet.hpp:48
Definition TGreenlet.hpp:572
Definition TGreenlet.hpp:617
Definition TGreenlet.hpp:343
virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState ¤t_thread_state)
Definition TGreenlet.cpp:60
OwnedObject on_switchstack_or_initialstub_failure(Greenlet *target, const switchstack_result_t &err, const bool target_was_me=false, const bool was_initial_stub=false)
Definition TGreenlet.cpp:101
virtual void murder_in_place()
Definition TGreenlet.cpp:499
void deactivate_and_free()
Definition TGreenlet.cpp:508
virtual switchstack_result_t g_switchstack(void)
Definition TGreenlet.cpp:146
Definition TGreenlet.hpp:752
Definition TGreenlet.hpp:72
Definition TGreenlet.hpp:105
Definition TGreenlet.hpp:185
StackState()
Definition TStackState.cpp:38
Definition TGreenlet.hpp:242
SwitchingArgs & operator<<=(SwitchingArgs &other)
Definition TGreenlet.hpp:277
SwitchingArgs & operator<<=(OwnedObject &args)
Definition TGreenlet.hpp:302
SwitchingArgs & operator<<=(PyObject *args)
Definition TGreenlet.hpp:290
Definition TThreadState.hpp:87
Definition TGreenlet.hpp:711
Definition TGreenlet.hpp:675
virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState ¤t_thread_state)
Definition TUserGreenlet.cpp:83
virtual void murder_in_place()
Definition TUserGreenlet.cpp:614
Definition greenlet_refs.hpp:600
Definition greenlet_refs.hpp:534
Definition greenlet_refs.hpp:686
Definition greenlet_refs.hpp:435
Definition greenlet_refs.hpp:301
Definition greenlet_refs.hpp:560
Definition greenlet_refs.hpp:471
OwnedObject & operator<<=(OwnedObject &lhs, greenlet::SwitchingArgs &rhs) noexcept
Definition TGreenlet.cpp:359
Definition TGreenlet.hpp:513
Definition greenlet_allocator.hpp:17