Загрузить файлы в «venv/Lib/site-packages/greenlet»
This commit is contained in:
76
venv/Lib/site-packages/greenlet/greenlet_allocator.hpp
Normal file
76
venv/Lib/site-packages/greenlet/greenlet_allocator.hpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#ifndef GREENLET_ALLOCATOR_HPP
|
||||||
|
#define GREENLET_ALLOCATOR_HPP
|
||||||
|
|
||||||
|
#define PY_SSIZE_T_CLEAN
|
||||||
|
#include <Python.h>
|
||||||
|
#include <memory>
|
||||||
|
#include "greenlet_compiler_compat.hpp"
|
||||||
|
#include "greenlet_cpython_compat.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace greenlet
|
||||||
|
{
|
||||||
|
// This allocator is stateless; all instances are identical.
|
||||||
|
// It can *ONLY* be used when we're sure we're holding the GIL
|
||||||
|
// (Python's allocators require the GIL).
|
||||||
|
template <class T>
|
||||||
|
struct PythonAllocator : public std::allocator<T> {
|
||||||
|
|
||||||
|
PythonAllocator(const PythonAllocator& UNUSED(other))
|
||||||
|
: std::allocator<T>()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PythonAllocator(const std::allocator<T> other)
|
||||||
|
: std::allocator<T>(other)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
PythonAllocator(const std::allocator<U>& other)
|
||||||
|
: std::allocator<T>(other)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PythonAllocator() : std::allocator<T>() {}
|
||||||
|
|
||||||
|
T* allocate(size_t number_objects, const void* UNUSED(hint)=0)
|
||||||
|
{
|
||||||
|
void* p;
|
||||||
|
if (number_objects == 1) {
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
p = PyMem_Malloc(sizeof(T) * number_objects);
|
||||||
|
#else
|
||||||
|
p = PyObject_Malloc(sizeof(T));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p = PyMem_Malloc(sizeof(T) * number_objects);
|
||||||
|
}
|
||||||
|
return static_cast<T*>(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(T* t, size_t n)
|
||||||
|
{
|
||||||
|
void* p = t;
|
||||||
|
if (n == 1) {
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyMem_Free(p);
|
||||||
|
#else
|
||||||
|
PyObject_Free(p);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyMem_Free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This member is deprecated in C++17 and removed in C++20
|
||||||
|
template< class U >
|
||||||
|
struct rebind {
|
||||||
|
typedef PythonAllocator<U> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
98
venv/Lib/site-packages/greenlet/greenlet_compiler_compat.hpp
Normal file
98
venv/Lib/site-packages/greenlet/greenlet_compiler_compat.hpp
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
|
||||||
|
#ifndef GREENLET_COMPILER_COMPAT_HPP
|
||||||
|
#define GREENLET_COMPILER_COMPAT_HPP
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definitions to aid with compatibility with different compilers.
|
||||||
|
*
|
||||||
|
* .. caution:: Use extreme care with noexcept.
|
||||||
|
* Some compilers and runtimes, specifically gcc/libgcc/libstdc++ on
|
||||||
|
* Linux, implement stack unwinding by throwing an uncatchable
|
||||||
|
* exception, one that specifically does not appear to be an active
|
||||||
|
* exception to the rest of the runtime. If this happens while we're in a noexcept function,
|
||||||
|
* we have violated our dynamic exception contract, and so the runtime
|
||||||
|
* will call std::terminate(), which kills the process with the
|
||||||
|
* unhelpful message "terminate called without an active exception".
|
||||||
|
*
|
||||||
|
* This has happened in this scenario: A background thread is running
|
||||||
|
* a greenlet that has made a native call and released the GIL.
|
||||||
|
* Meanwhile, the main thread finishes and starts shutting down the
|
||||||
|
* interpreter. When the background thread is scheduled again and
|
||||||
|
* attempts to obtain the GIL, it notices that the interpreter is
|
||||||
|
* exiting and calls ``pthread_exit()``. This in turn starts to unwind
|
||||||
|
* the stack by throwing that exception. But we had the ``PyCall``
|
||||||
|
* functions annotated as noexcept, so the runtime terminated us.
|
||||||
|
*
|
||||||
|
* #2 0x00007fab26fec2b7 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
|
||||||
|
* #3 0x00007fab26febb3c in __gxx_personality_v0 () from /lib/x86_64-linux-gnu/libstdc++.so.6
|
||||||
|
* #4 0x00007fab26f34de6 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
|
||||||
|
* #6 0x00007fab276a34c6 in __GI___pthread_unwind at ./nptl/unwind.c:130
|
||||||
|
* #7 0x00007fab2769bd3a in __do_cancel () at ../sysdeps/nptl/pthreadP.h:280
|
||||||
|
* #8 __GI___pthread_exit (value=value@entry=0x0) at ./nptl/pthread_exit.c:36
|
||||||
|
* #9 0x000000000052e567 in PyThread_exit_thread () at ../Python/thread_pthread.h:370
|
||||||
|
* #10 0x00000000004d60b5 in take_gil at ../Python/ceval_gil.h:224
|
||||||
|
* #11 0x00000000004d65f9 in PyEval_RestoreThread at ../Python/ceval.c:467
|
||||||
|
* #12 0x000000000060cce3 in setipaddr at ../Modules/socketmodule.c:1203
|
||||||
|
* #13 0x00000000006101cd in socket_gethostbyname
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
# define G_NO_COPIES_OF_CLS(Cls) private: \
|
||||||
|
Cls(const Cls& other) = delete; \
|
||||||
|
Cls& operator=(const Cls& other) = delete
|
||||||
|
|
||||||
|
# define G_NO_ASSIGNMENT_OF_CLS(Cls) private: \
|
||||||
|
Cls& operator=(const Cls& other) = delete
|
||||||
|
|
||||||
|
# define G_NO_COPY_CONSTRUCTOR_OF_CLS(Cls) private: \
|
||||||
|
Cls(const Cls& other) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
// CAUTION: MSVC is stupidly picky:
|
||||||
|
//
|
||||||
|
// "The compiler ignores, without warning, any __declspec keywords
|
||||||
|
// placed after * or & and in front of the variable identifier in a
|
||||||
|
// declaration."
|
||||||
|
// (https://docs.microsoft.com/en-us/cpp/cpp/declspec?view=msvc-160)
|
||||||
|
//
|
||||||
|
// So pointer return types must be handled differently (because of the
|
||||||
|
// trailing *), or you get inscrutable compiler warnings like "error
|
||||||
|
// C2059: syntax error: ''"
|
||||||
|
//
|
||||||
|
// In C++ 11, there is a standard syntax for attributes, and
|
||||||
|
// GCC defines an attribute to use with this: [[gnu:noinline]].
|
||||||
|
// In the future, this is expected to become standard.
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
/* We used to check for GCC 4+ or 3.4+, but those compilers are
|
||||||
|
laughably out of date. Just assume they support it. */
|
||||||
|
# define GREENLET_NOINLINE(name) __attribute__((noinline)) name
|
||||||
|
# define GREENLET_NOINLINE_P(rtype, name) rtype __attribute__((noinline)) name
|
||||||
|
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
/* We used to check for && (_MSC_VER >= 1300) but that's also out of date. */
|
||||||
|
# define GREENLET_NOINLINE(name) __declspec(noinline) name
|
||||||
|
# define GREENLET_NOINLINE_P(rtype, name) __declspec(noinline) rtype name
|
||||||
|
# define UNUSED(x) UNUSED_ ## x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define G_NOEXCEPT_WIN32 noexcept
|
||||||
|
#else
|
||||||
|
# define G_NOEXCEPT_WIN32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && defined(__POWERPC__) && defined(__APPLE__)
|
||||||
|
// 32-bit PPC/MacOSX. Only known to be tested on unreleased versions
|
||||||
|
// of macOS 10.6 using a macports build gcc 14. It appears that
|
||||||
|
// running C++ destructors of thread-local variables is broken.
|
||||||
|
|
||||||
|
// See https://github.com/python-greenlet/greenlet/pull/419
|
||||||
|
# define GREENLET_BROKEN_THREAD_LOCAL_CLEANUP_JUST_LEAK 1
|
||||||
|
#else
|
||||||
|
# define GREENLET_BROKEN_THREAD_LOCAL_CLEANUP_JUST_LEAK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
117
venv/Lib/site-packages/greenlet/greenlet_cpython_compat.hpp
Normal file
117
venv/Lib/site-packages/greenlet/greenlet_cpython_compat.hpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
|
||||||
|
#ifndef GREENLET_CPYTHON_COMPAT_H
|
||||||
|
#define GREENLET_CPYTHON_COMPAT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers for compatibility with multiple versions of CPython.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PY_SSIZE_T_CLEAN
|
||||||
|
#include "Python.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Python 3.10 beta 1 changed tstate->use_tracing to a nested cframe member.
|
||||||
|
See https://github.com/python/cpython/pull/25276
|
||||||
|
We have to save and restore this as well.
|
||||||
|
|
||||||
|
Python 3.13 removed PyThreadState.cframe (GH-108035).
|
||||||
|
*/
|
||||||
|
#if PY_VERSION_HEX < 0x30D0000
|
||||||
|
# define GREENLET_USE_CFRAME 1
|
||||||
|
#else
|
||||||
|
# define GREENLET_USE_CFRAME 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x30B00A4
|
||||||
|
/*
|
||||||
|
Greenlet won't compile on anything older than Python 3.11 alpha 4 (see
|
||||||
|
https://bugs.python.org/issue46090). Summary of breaking internal changes:
|
||||||
|
- Python 3.11 alpha 1 changed how frame objects are represented internally.
|
||||||
|
- https://github.com/python/cpython/pull/30122
|
||||||
|
- Python 3.11 alpha 3 changed how recursion limits are stored.
|
||||||
|
- https://github.com/python/cpython/pull/29524
|
||||||
|
- Python 3.11 alpha 4 changed how exception state is stored. It also includes a
|
||||||
|
change to help greenlet save and restore the interpreter frame "data stack".
|
||||||
|
- https://github.com/python/cpython/pull/30122
|
||||||
|
- https://github.com/python/cpython/pull/30234
|
||||||
|
*/
|
||||||
|
# define GREENLET_PY311 1
|
||||||
|
#else
|
||||||
|
# define GREENLET_PY311 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x30C0000
|
||||||
|
# define GREENLET_PY312 1
|
||||||
|
#else
|
||||||
|
# define GREENLET_PY312 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x30D0000
|
||||||
|
# define GREENLET_PY313 1
|
||||||
|
#else
|
||||||
|
# define GREENLET_PY313 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x30E0000
|
||||||
|
# define GREENLET_PY314 1
|
||||||
|
#else
|
||||||
|
# define GREENLET_PY314 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x30F0000
|
||||||
|
# define GREENLET_PY315 1
|
||||||
|
#else
|
||||||
|
# define GREENLET_PY315 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* _Py_DEC_REFTOTAL macro has been removed from Python 3.9 by:
|
||||||
|
https://github.com/python/cpython/commit/49932fec62c616ec88da52642339d83ae719e924
|
||||||
|
|
||||||
|
The symbol we use to replace it was removed by at least 3.12.
|
||||||
|
*/
|
||||||
|
#if defined(Py_REF_DEBUG) && !GREENLET_PY312
|
||||||
|
# define GREENLET_Py_DEC_REFTOTAL _Py_RefTotal--
|
||||||
|
#else
|
||||||
|
# define GREENLET_Py_DEC_REFTOTAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define G_TPFLAGS_DEFAULT Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_VERSION_TAG | Py_TPFLAGS_HAVE_GC
|
||||||
|
|
||||||
|
|
||||||
|
// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2
|
||||||
|
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
|
||||||
|
static inline void PyThreadState_EnterTracing(PyThreadState *tstate)
|
||||||
|
{
|
||||||
|
tstate->tracing++;
|
||||||
|
tstate->cframe->use_tracing = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2
|
||||||
|
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
|
||||||
|
static inline void PyThreadState_LeaveTracing(PyThreadState *tstate)
|
||||||
|
{
|
||||||
|
tstate->tracing--;
|
||||||
|
int use_tracing = (tstate->c_tracefunc != NULL
|
||||||
|
|| tstate->c_profilefunc != NULL);
|
||||||
|
tstate->cframe->use_tracing = use_tracing;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(Py_C_RECURSION_LIMIT) && defined(C_RECURSION_LIMIT)
|
||||||
|
# define Py_C_RECURSION_LIMIT C_RECURSION_LIMIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Py_IsFinalizing() became a public API in Python 3.13. Map it to the
|
||||||
|
// private _Py_IsFinalizing() on older versions so all call sites can
|
||||||
|
// use the standard name. Remove this once greenlet drops support for
|
||||||
|
// Python < 3.13.
|
||||||
|
#if !GREENLET_PY313
|
||||||
|
# define Py_IsFinalizing() _Py_IsFinalizing()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* GREENLET_CPYTHON_COMPAT_H */
|
||||||
171
venv/Lib/site-packages/greenlet/greenlet_exceptions.hpp
Normal file
171
venv/Lib/site-packages/greenlet/greenlet_exceptions.hpp
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
#ifndef GREENLET_EXCEPTIONS_HPP
|
||||||
|
#define GREENLET_EXCEPTIONS_HPP
|
||||||
|
|
||||||
|
#define PY_SSIZE_T_CLEAN
|
||||||
|
#include <Python.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace greenlet {
|
||||||
|
|
||||||
|
class PyErrOccurred : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// CAUTION: In debug builds, may run arbitrary Python code.
|
||||||
|
static const PyErrOccurred
|
||||||
|
from_current()
|
||||||
|
{
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// This is not exception safe, and
|
||||||
|
// not necessarily safe in general (what if it switches?)
|
||||||
|
// But we only do this in debug mode, where we are in
|
||||||
|
// tight control of what exceptions are getting raised and
|
||||||
|
// can prevent those issues.
|
||||||
|
|
||||||
|
// You can't call PyObject_Str with a pending exception.
|
||||||
|
PyObject* typ;
|
||||||
|
PyObject* val;
|
||||||
|
PyObject* tb;
|
||||||
|
|
||||||
|
PyErr_Fetch(&typ, &val, &tb);
|
||||||
|
PyObject* typs = PyObject_Str(typ);
|
||||||
|
PyObject* vals = PyObject_Str(val ? val : typ);
|
||||||
|
const char* typ_msg = PyUnicode_AsUTF8(typs);
|
||||||
|
const char* val_msg = PyUnicode_AsUTF8(vals);
|
||||||
|
PyErr_Restore(typ, val, tb);
|
||||||
|
|
||||||
|
std::string msg(typ_msg);
|
||||||
|
msg += ": ";
|
||||||
|
msg += val_msg;
|
||||||
|
PyErrOccurred ex(msg);
|
||||||
|
Py_XDECREF(typs);
|
||||||
|
Py_XDECREF(vals);
|
||||||
|
|
||||||
|
return ex;
|
||||||
|
#else
|
||||||
|
return PyErrOccurred();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErrOccurred() : std::runtime_error("")
|
||||||
|
{
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErrOccurred(const std::string& msg) : std::runtime_error(msg)
|
||||||
|
{
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErrOccurred(PyObject* exc_kind, const char* const msg)
|
||||||
|
: std::runtime_error(msg)
|
||||||
|
{
|
||||||
|
PyErr_SetString(exc_kind, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErrOccurred(PyObject* exc_kind, const std::string msg)
|
||||||
|
: std::runtime_error(msg)
|
||||||
|
{
|
||||||
|
// This copies the c_str, so we don't have any lifetime
|
||||||
|
// issues to worry about.
|
||||||
|
PyErr_SetString(exc_kind, msg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErrOccurred(PyObject* exc_kind,
|
||||||
|
const std::string msg, //This is the format
|
||||||
|
//string; that's not
|
||||||
|
//usually safe!
|
||||||
|
|
||||||
|
PyObject* borrowed_obj_one, PyObject* borrowed_obj_two)
|
||||||
|
: std::runtime_error(msg)
|
||||||
|
{
|
||||||
|
|
||||||
|
//This is designed specifically for the
|
||||||
|
//``check_switch_allowed`` function.
|
||||||
|
|
||||||
|
// PyObject_Str and PyObject_Repr are safe to call with
|
||||||
|
// NULL pointers; they return the string "<NULL>" in that
|
||||||
|
// case.
|
||||||
|
// This function always returns null.
|
||||||
|
PyErr_Format(exc_kind,
|
||||||
|
msg.c_str(),
|
||||||
|
borrowed_obj_one, borrowed_obj_two);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TypeError : public PyErrOccurred
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TypeError(const char* const what)
|
||||||
|
: PyErrOccurred(PyExc_TypeError, what)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
TypeError(const std::string what)
|
||||||
|
: PyErrOccurred(PyExc_TypeError, what)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ValueError : public PyErrOccurred
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ValueError(const char* const what)
|
||||||
|
: PyErrOccurred(PyExc_ValueError, what)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AttributeError : public PyErrOccurred
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AttributeError(const char* const what)
|
||||||
|
: PyErrOccurred(PyExc_AttributeError, what)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls `Py_FatalError` when constructed, so you can't actually
|
||||||
|
* throw this. It just makes static analysis easier.
|
||||||
|
*/
|
||||||
|
class PyFatalError : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PyFatalError(const char* const msg)
|
||||||
|
: std::runtime_error(msg)
|
||||||
|
{
|
||||||
|
Py_FatalError(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline PyObject*
|
||||||
|
Require(PyObject* p, const std::string& msg="")
|
||||||
|
{
|
||||||
|
if (!p) {
|
||||||
|
throw PyErrOccurred(msg);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
Require(const int retval)
|
||||||
|
{
|
||||||
|
if (retval < 0) {
|
||||||
|
throw PyErrOccurred();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
109
venv/Lib/site-packages/greenlet/greenlet_internal.hpp
Normal file
109
venv/Lib/site-packages/greenlet/greenlet_internal.hpp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
|
||||||
|
#ifndef GREENLET_INTERNAL_H
|
||||||
|
#define GREENLET_INTERNAL_H
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation helpers.
|
||||||
|
*
|
||||||
|
* C++ templates and inline functions should go here.
|
||||||
|
*/
|
||||||
|
#define PY_SSIZE_T_CLEAN
|
||||||
|
#include "greenlet_compiler_compat.hpp"
|
||||||
|
#include "greenlet_cpython_compat.hpp"
|
||||||
|
#include "greenlet_exceptions.hpp"
|
||||||
|
#include "TGreenlet.hpp"
|
||||||
|
#include "greenlet_allocator.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define GREENLET_MODULE
|
||||||
|
struct _greenlet;
|
||||||
|
typedef struct _greenlet PyGreenlet;
|
||||||
|
namespace greenlet {
|
||||||
|
|
||||||
|
class ThreadState;
|
||||||
|
// We can't use the PythonAllocator for this, because we push to it
|
||||||
|
// from the thread state destructor, which doesn't have the GIL,
|
||||||
|
// and Python's allocators can only be called with the GIL.
|
||||||
|
typedef std::vector<ThreadState*> cleanup_queue_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define implementation_ptr_t greenlet::Greenlet*
|
||||||
|
|
||||||
|
|
||||||
|
#include "greenlet.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
greenlet::refs::MainGreenletExactChecker(void *p)
|
||||||
|
{
|
||||||
|
if (!p) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (greenlet::IsShuttingDown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We control the class of the main greenlet exactly.
|
||||||
|
if (Py_TYPE(p) != &PyGreenlet_Type) {
|
||||||
|
std::string err("MainGreenlet: Expected exactly a greenlet, not a ");
|
||||||
|
err += Py_TYPE(p)->tp_name;
|
||||||
|
throw greenlet::TypeError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Greenlets from dead threads no longer respond to main() with a
|
||||||
|
// true value; so in that case we need to perform an additional
|
||||||
|
// check.
|
||||||
|
Greenlet* g = static_cast<PyGreenlet*>(p)->pimpl;
|
||||||
|
if (g->main()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dynamic_cast<MainGreenlet*>(g)) {
|
||||||
|
std::string err("MainGreenlet: Expected exactly a main greenlet, not a ");
|
||||||
|
err += Py_TYPE(p)->tp_name;
|
||||||
|
throw greenlet::TypeError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, greenlet::refs::TypeChecker TC>
|
||||||
|
inline greenlet::Greenlet* greenlet::refs::_OwnedGreenlet<T, TC>::operator->() const noexcept
|
||||||
|
{
|
||||||
|
return reinterpret_cast<PyGreenlet*>(this->p)->pimpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, greenlet::refs::TypeChecker TC>
|
||||||
|
inline greenlet::Greenlet* greenlet::refs::_BorrowedGreenlet<T, TC>::operator->() const noexcept
|
||||||
|
{
|
||||||
|
return reinterpret_cast<PyGreenlet*>(this->p)->pimpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
|
extern PyTypeObject PyGreenlet_Type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward declarations needed in multiple files.
|
||||||
|
*/
|
||||||
|
static PyObject* green_switch(PyGreenlet* self, PyObject* args, PyObject* kwargs);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Local Variables:
|
||||||
|
// flycheck-clang-include-path: ("../../include" "/opt/local/Library/Frameworks/Python.framework/Versions/3.10/include/python3.10")
|
||||||
|
// End:
|
||||||
Reference in New Issue
Block a user