From 12cf076118570eebbff08c6b3090e0d4798447a1 Mon Sep 17 00:00:00 2001 From: cyfraeviolae Date: Wed, 3 Apr 2024 03:17:55 -0400 Subject: no venv --- .../site-packages/greenlet/greenlet_greenlet.hpp | 805 --------------------- 1 file changed, 805 deletions(-) delete mode 100644 venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp (limited to 'venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp') diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp deleted file mode 100644 index d52ce1f..0000000 --- a/venv/lib/python3.11/site-packages/greenlet/greenlet_greenlet.hpp +++ /dev/null @@ -1,805 +0,0 @@ -#ifndef GREENLET_GREENLET_HPP -#define GREENLET_GREENLET_HPP -/* - * Declarations of the core data structures. -*/ - -#define PY_SSIZE_T_CLEAN -#include - -#include "greenlet_compiler_compat.hpp" -#include "greenlet_refs.hpp" -#include "greenlet_cpython_compat.hpp" -#include "greenlet_allocator.hpp" - -using greenlet::refs::OwnedObject; -using greenlet::refs::OwnedGreenlet; -using greenlet::refs::OwnedMainGreenlet; -using greenlet::refs::BorrowedGreenlet; - -#if PY_VERSION_HEX < 0x30B00A6 -# define _PyCFrame CFrame -# define _PyInterpreterFrame _interpreter_frame -#endif - -#if GREENLET_PY312 -# include "internal/pycore_frame.h" -#endif - -// XXX: TODO: Work to remove all virtual functions -// for speed of calling and size of objects (no vtable). -// One pattern is the Curiously Recurring Template -namespace greenlet -{ - class ExceptionState - { - private: - G_NO_COPIES_OF_CLS(ExceptionState); - - // Even though these are borrowed objects, we actually own - // them, when they're not null. - // XXX: Express that in the API. - private: - _PyErr_StackItem* exc_info; - _PyErr_StackItem exc_state; - public: - ExceptionState(); - void operator<<(const PyThreadState *const tstate) noexcept; - void operator>>(PyThreadState* tstate) noexcept; - void clear() noexcept; - - int tp_traverse(visitproc visit, void* arg) noexcept; - void tp_clear() noexcept; - }; - - template - void operator<<(const PyThreadState *const tstate, T& exc); - - class PythonStateContext - { - protected: - greenlet::refs::OwnedContext _context; - public: - inline const greenlet::refs::OwnedContext& context() const - { - return this->_context; - } - inline greenlet::refs::OwnedContext& context() - { - return this->_context; - } - - inline void tp_clear() - { - this->_context.CLEAR(); - } - - template - inline static PyObject* context(T* tstate) - { - return tstate->context; - } - - template - inline static void context(T* tstate, PyObject* new_context) - { - tstate->context = new_context; - tstate->context_ver++; - } - }; - class SwitchingArgs; - class PythonState : public PythonStateContext - { - public: - typedef greenlet::refs::OwnedReference OwnedFrame; - private: - G_NO_COPIES_OF_CLS(PythonState); - // We own this if we're suspended (although currently we don't - // tp_traverse into it; that's a TODO). If we're running, it's - // empty. If we get deallocated and *still* have a frame, it - // won't be reachable from the place that normally decref's - // it, so we need to do it (hence owning it). - OwnedFrame _top_frame; -#if GREENLET_USE_CFRAME - _PyCFrame* cframe; - int use_tracing; -#endif -#if GREENLET_PY312 - int py_recursion_depth; - int c_recursion_depth; -#else - int recursion_depth; -#endif - int trash_delete_nesting; -#if GREENLET_PY311 - _PyInterpreterFrame* current_frame; - _PyStackChunk* datastack_chunk; - PyObject** datastack_top; - PyObject** datastack_limit; -#endif - // The PyInterpreterFrame list on 3.12+ contains some entries that are - // on the C stack, which can't be directly accessed while a greenlet is - // suspended. In order to keep greenlet gr_frame introspection working, - // we adjust stack switching to rewrite the interpreter frame list - // to skip these C-stack frames; we call this "exposing" the greenlet's - // frames because it makes them valid to work with in Python. Then when - // the greenlet is resumed we need to remember to reverse the operation - // we did. The C-stack frames are "entry frames" which are a low-level - // interpreter detail; they're not needed for introspection, but do - // need to be present for the eval loop to work. - void unexpose_frames(); - - public: - - PythonState(); - // You can use this for testing whether we have a frame - // or not. It returns const so they can't modify it. - const OwnedFrame& top_frame() const noexcept; - - inline void operator<<(const PyThreadState *const tstate) noexcept; - inline void operator>>(PyThreadState* tstate) noexcept; - void clear() noexcept; - - int tp_traverse(visitproc visit, void* arg, bool visit_top_frame) noexcept; - void tp_clear(bool own_top_frame) noexcept; - void set_initial_state(const PyThreadState* const tstate) noexcept; -#if GREENLET_USE_CFRAME - void set_new_cframe(_PyCFrame& frame) noexcept; -#endif - - inline void may_switch_away() noexcept; - inline void will_switch_from(PyThreadState *const origin_tstate) noexcept; - void did_finish(PyThreadState* tstate) noexcept; - }; - - class StackState - { - // By having only plain C (POD) members, no virtual functions - // or bases, we get a trivial assignment operator generated - // for us. However, that's not safe since we do manage memory. - // So we declare an assignment operator that only works if we - // don't have any memory allocated. (We don't use - // std::shared_ptr for reference counting just to keep this - // object small) - private: - char* _stack_start; - char* stack_stop; - char* stack_copy; - intptr_t _stack_saved; - StackState* stack_prev; - inline int copy_stack_to_heap_up_to(const char* const stop) noexcept; - inline void free_stack_copy() noexcept; - - public: - /** - * Creates a started, but inactive, state, using *current* - * as the previous. - */ - StackState(void* mark, StackState& current); - /** - * Creates an inactive, unstarted, state. - */ - StackState(); - ~StackState(); - StackState(const StackState& other); - StackState& operator=(const StackState& other); - inline void copy_heap_to_stack(const StackState& current) noexcept; - inline int copy_stack_to_heap(char* const stackref, const StackState& current) noexcept; - inline bool started() const noexcept; - inline bool main() const noexcept; - inline bool active() const noexcept; - inline void set_active() noexcept; - inline void set_inactive() noexcept; - inline intptr_t stack_saved() const noexcept; - inline char* stack_start() const noexcept; - static inline StackState make_main() noexcept; -#ifdef GREENLET_USE_STDIO - friend std::ostream& operator<<(std::ostream& os, const StackState& s); -#endif - - // Fill in [dest, dest + n) with the values that would be at - // [src, src + n) while this greenlet is running. This is like memcpy - // except that if the greenlet is suspended it accounts for the portion - // of the greenlet's stack that was spilled to the heap. `src` may - // be on this greenlet's stack, or on the heap, but not on a different - // greenlet's stack. - void copy_from_stack(void* dest, const void* src, size_t n) const; - }; -#ifdef GREENLET_USE_STDIO - std::ostream& operator<<(std::ostream& os, const StackState& s); -#endif - - class SwitchingArgs - { - private: - G_NO_ASSIGNMENT_OF_CLS(SwitchingArgs); - // If args and kwargs are both false (NULL), this is a *throw*, not a - // switch. PyErr_... must have been called already. - OwnedObject _args; - OwnedObject _kwargs; - public: - - SwitchingArgs() - {} - - SwitchingArgs(const OwnedObject& args, const OwnedObject& kwargs) - : _args(args), - _kwargs(kwargs) - {} - - SwitchingArgs(const SwitchingArgs& other) - : _args(other._args), - _kwargs(other._kwargs) - {} - - const OwnedObject& args() - { - return this->_args; - } - - const OwnedObject& kwargs() - { - return this->_kwargs; - } - - /** - * Moves ownership from the argument to this object. - */ - SwitchingArgs& operator<<=(SwitchingArgs& other) - { - if (this != &other) { - this->_args = other._args; - this->_kwargs = other._kwargs; - other.CLEAR(); - } - return *this; - } - - /** - * Acquires ownership of the argument (consumes the reference). - */ - SwitchingArgs& operator<<=(PyObject* args) - { - this->_args = OwnedObject::consuming(args); - this->_kwargs.CLEAR(); - return *this; - } - - /** - * Acquires ownership of the argument. - * - * Sets the args to be the given value; clears the kwargs. - */ - SwitchingArgs& operator<<=(OwnedObject& args) - { - assert(&args != &this->_args); - this->_args = args; - this->_kwargs.CLEAR(); - args.CLEAR(); - - return *this; - } - - explicit operator bool() const noexcept - { - return this->_args || this->_kwargs; - } - - inline void CLEAR() - { - this->_args.CLEAR(); - this->_kwargs.CLEAR(); - } - - const std::string as_str() const noexcept - { - return PyUnicode_AsUTF8( - OwnedObject::consuming( - PyUnicode_FromFormat( - "SwitchingArgs(args=%R, kwargs=%R)", - this->_args.borrow(), - this->_kwargs.borrow() - ) - ).borrow() - ); - } - }; - - class ThreadState; - - class UserGreenlet; - class MainGreenlet; - - class Greenlet - { - private: - G_NO_COPIES_OF_CLS(Greenlet); - private: - // XXX: Work to remove these. - friend class ThreadState; - friend class UserGreenlet; - friend class MainGreenlet; - protected: - ExceptionState exception_state; - SwitchingArgs switch_args; - StackState stack_state; - PythonState python_state; - Greenlet(PyGreenlet* p, const StackState& initial_state); - public: - Greenlet(PyGreenlet* p); - virtual ~Greenlet(); - - const OwnedObject context() const; - - // You MUST call this _very_ early in the switching process to - // prepare anything that may need prepared. This might perform - // garbage collections or otherwise run arbitrary Python code. - // - // One specific use of it is for Python 3.11+, preventing - // running arbitrary code at unsafe times. See - // PythonState::may_switch_away(). - inline void may_switch_away() - { - this->python_state.may_switch_away(); - } - - inline void context(refs::BorrowedObject new_context); - - inline SwitchingArgs& args() - { - return this->switch_args; - } - - virtual const refs::BorrowedMainGreenlet main_greenlet() const = 0; - - inline intptr_t stack_saved() const noexcept - { - return this->stack_state.stack_saved(); - } - - // This is used by the macro SLP_SAVE_STATE to compute the - // difference in stack sizes. It might be nice to handle the - // computation ourself, but the type of the result - // varies by platform, so doing it in the macro is the - // simplest way. - inline const char* stack_start() const noexcept - { - return this->stack_state.stack_start(); - } - - virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state); - virtual OwnedObject g_switch() = 0; - /** - * Force the greenlet to appear dead. Used when it's not - * possible to throw an exception into a greenlet anymore. - * - * This losses access to the thread state and the main greenlet. - */ - virtual void murder_in_place(); - - /** - * Called when somebody notices we were running in a dead - * thread to allow cleaning up resources (because we can't - * raise GreenletExit into it anymore). - * This is very similar to ``murder_in_place()``, except that - * it DOES NOT lose the main greenlet or thread state. - */ - inline void deactivate_and_free(); - - - // Called when some thread wants to deallocate a greenlet - // object. - // The thread may or may not be the same thread the greenlet - // was running in. - // The thread state will be null if the thread the greenlet - // was running in was known to have exited. - void deallocing_greenlet_in_thread(const ThreadState* current_state); - - // Must be called on 3.12+ before exposing a suspended greenlet's - // frames to user code. This rewrites the linked list of interpreter - // frames to skip the ones that are being stored on the C stack (which - // can't be safely accessed while the greenlet is suspended because - // that stack space might be hosting a different greenlet), and - // sets PythonState::frames_were_exposed so we remember to restore - // the original list before resuming the greenlet. The C-stack frames - // are a low-level interpreter implementation detail; while they're - // important to the bytecode eval loop, they're superfluous for - // introspection purposes. - void expose_frames(); - - - // TODO: Figure out how to make these non-public. - inline void slp_restore_state() noexcept; - inline int slp_save_state(char *const stackref) noexcept; - - inline bool is_currently_running_in_some_thread() const; - virtual bool belongs_to_thread(const ThreadState* state) const; - - inline bool started() const - { - return this->stack_state.started(); - } - inline bool active() const - { - return this->stack_state.active(); - } - inline bool main() const - { - return this->stack_state.main(); - } - virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const = 0; - - virtual const OwnedGreenlet parent() const = 0; - virtual void parent(const refs::BorrowedObject new_parent) = 0; - - inline const PythonState::OwnedFrame& top_frame() - { - return this->python_state.top_frame(); - } - - virtual const OwnedObject& run() const = 0; - virtual void run(const refs::BorrowedObject nrun) = 0; - - - virtual int tp_traverse(visitproc visit, void* arg); - virtual int tp_clear(); - - - // Return the thread state that the greenlet is running in, or - // null if the greenlet is not running or the thread is known - // to have exited. - virtual ThreadState* thread_state() const noexcept = 0; - - // Return true if the greenlet is known to have been running - // (active) in a thread that has now exited. - virtual bool was_running_in_dead_thread() const noexcept = 0; - - // Return a borrowed greenlet that is the Python object - // this object represents. - virtual BorrowedGreenlet self() const noexcept = 0; - - // For testing. If this returns true, we should pretend that - // slp_switch() failed. - virtual bool force_slp_switch_error() const noexcept; - - protected: - inline void release_args(); - - // The functions that must not be inlined are declared virtual. - // We also mark them as protected, not private, so that the - // compiler is forced to call them through a function pointer. - // (A sufficiently smart compiler could directly call a private - // virtual function since it can never be overridden in a - // subclass). - - // Also TODO: Switch away from integer error codes and to enums, - // or throw exceptions when possible. - struct switchstack_result_t - { - int status; - Greenlet* the_new_current_greenlet; - OwnedGreenlet origin_greenlet; - - switchstack_result_t() - : status(0), - the_new_current_greenlet(nullptr) - {} - - switchstack_result_t(int err) - : status(err), - the_new_current_greenlet(nullptr) - {} - - switchstack_result_t(int err, Greenlet* state, OwnedGreenlet& origin) - : status(err), - the_new_current_greenlet(state), - origin_greenlet(origin) - { - } - - switchstack_result_t(int err, Greenlet* state, const BorrowedGreenlet& origin) - : status(err), - the_new_current_greenlet(state), - origin_greenlet(origin) - { - } - - switchstack_result_t(const switchstack_result_t& other) - : status(other.status), - the_new_current_greenlet(other.the_new_current_greenlet), - origin_greenlet(other.origin_greenlet) - {} - - switchstack_result_t& operator=(const switchstack_result_t& other) - { - this->status = other.status; - this->the_new_current_greenlet = other.the_new_current_greenlet; - this->origin_greenlet = other.origin_greenlet; - return *this; - } - }; - - 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); - - // Returns the previous greenlet we just switched away from. - virtual OwnedGreenlet g_switchstack_success() noexcept; - - - // Check the preconditions for switching to this greenlet; if they - // aren't met, throws PyErrOccurred. Most callers will want to - // catch this and clear the arguments - inline void check_switch_allowed() const; - class GreenletStartedWhileInPython : public std::runtime_error - { - public: - GreenletStartedWhileInPython() : std::runtime_error("") - {} - }; - - protected: - - - /** - Perform a stack switch into this greenlet. - - This temporarily sets the global variable - ``switching_thread_state`` to this greenlet; as soon as the - call to ``slp_switch`` completes, this is reset to NULL. - Consequently, this depends on the GIL. - - TODO: Adopt the stackman model and pass ``slp_switch`` a - callback function and context pointer; this eliminates the - need for global variables altogether. - - Because the stack switch happens in this function, this - function can't use its own stack (local) variables, set - before the switch, and then accessed after the switch. - - Further, you con't even access ``g_thread_state_global`` - before and after the switch from the global variable. - Because it is thread local some compilers cache it in a - register/on the stack, notably new versions of MSVC; this - breaks with strange crashes sometime later, because writing - to anything in ``g_thread_state_global`` after the switch - is actually writing to random memory. For this reason, we - call a non-inlined function to finish the operation. (XXX: - The ``/GT`` MSVC compiler argument probably fixes that.) - - It is very important that stack switch is 'atomic', i.e. no - calls into other Python code allowed (except very few that - are safe), because global variables are very fragile. (This - should no longer be the case with thread-local variables.) - - */ - // Made virtual to facilitate subclassing UserGreenlet for testing. - virtual switchstack_result_t g_switchstack(void); - -class TracingGuard -{ -private: - PyThreadState* tstate; -public: - TracingGuard() - : tstate(PyThreadState_GET()) - { - PyThreadState_EnterTracing(this->tstate); - } - - ~TracingGuard() - { - PyThreadState_LeaveTracing(this->tstate); - this->tstate = nullptr; - } - - inline void CallTraceFunction(const OwnedObject& tracefunc, - const greenlet::refs::ImmortalEventName& event, - const BorrowedGreenlet& origin, - const BorrowedGreenlet& target) - { - // TODO: This calls tracefunc(event, (origin, target)). Add a shortcut - // function for that that's specialized to avoid the Py_BuildValue - // string parsing, or start with just using "ON" format with PyTuple_Pack(2, - // origin, target). That seems like what the N format is meant - // for. - // XXX: Why does event not automatically cast back to a PyObject? - // It tries to call the "deleted constructor ImmortalEventName - // const" instead. - assert(tracefunc); - assert(event); - assert(origin); - assert(target); - greenlet::refs::NewReference retval( - PyObject_CallFunction( - tracefunc.borrow(), - "O(OO)", - event.borrow(), - origin.borrow(), - target.borrow() - )); - if (!retval) { - throw PyErrOccurred::from_current(); - } - } -}; - - static void - g_calltrace(const OwnedObject& tracefunc, - const greenlet::refs::ImmortalEventName& event, - const greenlet::refs::BorrowedGreenlet& origin, - const BorrowedGreenlet& target); - private: - OwnedObject g_switch_finish(const switchstack_result_t& err); - - }; - - class UserGreenlet : public Greenlet - { - private: - static greenlet::PythonAllocator allocator; - BorrowedGreenlet _self; - OwnedMainGreenlet _main_greenlet; - OwnedObject _run_callable; - OwnedGreenlet _parent; - public: - static void* operator new(size_t UNUSED(count)); - static void operator delete(void* ptr); - - UserGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent); - virtual ~UserGreenlet(); - - virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const; - virtual bool was_running_in_dead_thread() const noexcept; - virtual ThreadState* thread_state() const noexcept; - virtual OwnedObject g_switch(); - virtual const OwnedObject& run() const - { - if (this->started() || !this->_run_callable) { - throw AttributeError("run"); - } - return this->_run_callable; - } - virtual void run(const refs::BorrowedObject nrun); - - virtual const OwnedGreenlet parent() const; - virtual void parent(const refs::BorrowedObject new_parent); - - virtual const refs::BorrowedMainGreenlet main_greenlet() const; - - virtual BorrowedGreenlet self() const noexcept; - virtual void murder_in_place(); - virtual bool belongs_to_thread(const ThreadState* state) const; - virtual int tp_traverse(visitproc visit, void* arg); - virtual int tp_clear(); - class ParentIsCurrentGuard - { - private: - OwnedGreenlet oldparent; - UserGreenlet* greenlet; - G_NO_COPIES_OF_CLS(ParentIsCurrentGuard); - public: - ParentIsCurrentGuard(UserGreenlet* p, const ThreadState& thread_state); - ~ParentIsCurrentGuard(); - }; - virtual OwnedObject throw_GreenletExit_during_dealloc(const ThreadState& current_thread_state); - protected: - virtual switchstack_result_t g_initialstub(void* mark); - private: - // This function isn't meant to return. - // This accepts raw pointers and the ownership of them at the - // same time. The caller should use ``inner_bootstrap(origin.relinquish_ownership())``. - void inner_bootstrap(PyGreenlet* origin_greenlet, PyObject* run); - }; - - class BrokenGreenlet : public UserGreenlet - { - private: - static greenlet::PythonAllocator allocator; - public: - bool _force_switch_error = false; - bool _force_slp_switch_error = false; - - static void* operator new(size_t UNUSED(count)); - static void operator delete(void* ptr); - BrokenGreenlet(PyGreenlet* p, BorrowedGreenlet the_parent) - : UserGreenlet(p, the_parent) - {} - virtual ~BrokenGreenlet() - {} - - virtual switchstack_result_t g_switchstack(void); - virtual bool force_slp_switch_error() const noexcept; - - }; - - class MainGreenlet : public Greenlet - { - private: - static greenlet::PythonAllocator allocator; - refs::BorrowedMainGreenlet _self; - ThreadState* _thread_state; - G_NO_COPIES_OF_CLS(MainGreenlet); - public: - static void* operator new(size_t UNUSED(count)); - static void operator delete(void* ptr); - - MainGreenlet(refs::BorrowedMainGreenlet::PyType*, ThreadState*); - virtual ~MainGreenlet(); - - - virtual const OwnedObject& run() const; - virtual void run(const refs::BorrowedObject nrun); - - virtual const OwnedGreenlet parent() const; - virtual void parent(const refs::BorrowedObject new_parent); - - virtual const refs::BorrowedMainGreenlet main_greenlet() const; - - virtual refs::BorrowedMainGreenlet find_main_greenlet_in_lineage() const; - virtual bool was_running_in_dead_thread() const noexcept; - virtual ThreadState* thread_state() const noexcept; - void thread_state(ThreadState*) noexcept; - virtual OwnedObject g_switch(); - virtual BorrowedGreenlet self() const noexcept; - virtual int tp_traverse(visitproc visit, void* arg); - }; - - // Instantiate one on the stack to save the GC state, - // and then disable GC. When it goes out of scope, GC will be - // restored to its original state. Sadly, these APIs are only - // available on 3.10+; luckily, we only need them on 3.11+. -#if GREENLET_PY310 - class GCDisabledGuard - { - private: - int was_enabled = 0; - public: - GCDisabledGuard() - : was_enabled(PyGC_IsEnabled()) - { - PyGC_Disable(); - } - - ~GCDisabledGuard() - { - if (this->was_enabled) { - PyGC_Enable(); - } - } - }; -#endif - - OwnedObject& operator<<=(OwnedObject& lhs, greenlet::SwitchingArgs& rhs) noexcept; - - //TODO: Greenlet::g_switch() should call this automatically on its - //return value. As it is, the module code is calling it. - static inline OwnedObject - single_result(const OwnedObject& results) - { - if (results - && PyTuple_Check(results.borrow()) - && PyTuple_GET_SIZE(results.borrow()) == 1) { - PyObject* result = PyTuple_GET_ITEM(results.borrow(), 0); - assert(result); - return OwnedObject::owning(result); - } - return results; - } - - - static OwnedObject - g_handle_exit(const OwnedObject& greenlet_result); - - - template - void operator<<(const PyThreadState *const lhs, T& rhs) - { - rhs.operator<<(lhs); - } - -} // namespace greenlet ; - -#endif -- cgit v1.2.3