1#ifndef GREENLET_REFS_HPP
2#define GREENLET_REFS_HPP
4#define PY_SSIZE_T_CLEAN
10#include "greenlet_compiler_compat.hpp"
11#include "greenlet_cpython_compat.hpp"
12#include "greenlet_exceptions.hpp"
15struct _PyMainGreenlet;
18extern PyTypeObject PyGreenlet_Type;
21#ifdef GREENLET_USE_STDIO
38 typedef void (*TypeChecker)(
void*);
47 GreenletChecker(
void *p)
53 PyTypeObject* typ = Py_TYPE(p);
58 if (typ == &PyGreenlet_Type) {
62 if (!PyObject_TypeCheck(p, &PyGreenlet_Type)) {
63 std::string err(
"GreenletChecker: Expected any type of greenlet, not ");
64 err += Py_TYPE(p)->tp_name;
70 MainGreenletExactChecker(
void *p);
72 template <
typename T, TypeChecker>
73 class PyObjectPointer;
75 template<
typename T, TypeChecker>
79 template<
typename T, TypeChecker>
80 class BorrowedReference;
82 typedef BorrowedReference<PyObject, NoOpChecker> BorrowedObject;
83 typedef OwnedReference<PyObject, NoOpChecker> OwnedObject;
88 template<
typename T, TypeChecker TC>
91 typedef _OwnedGreenlet<PyGreenlet, GreenletChecker> OwnedGreenlet;
92 typedef _OwnedGreenlet<PyGreenlet, MainGreenletExactChecker> OwnedMainGreenlet;
94 template<
typename T, TypeChecker TC>
95 class _BorrowedGreenlet;
97 typedef _BorrowedGreenlet<PyGreenlet, GreenletChecker> BorrowedGreenlet;
100 ContextExactChecker(
void *p)
105 if (!PyContext_CheckExact(p)) {
107 "greenlet context must be a contextvars.Context or None"
112 typedef OwnedReference<PyObject, ContextExactChecker> OwnedContext;
169 template <
typename T=PyObject, TypeChecker TC=NoOpChecker>
192 T* borrow()
const noexcept
197 PyObject* borrow_o()
const noexcept
199 return reinterpret_cast<PyObject*
>(this->p);
202 T* operator->()
const noexcept
207 bool is_None()
const noexcept
209 return this->p == Py_None;
212 PyObject* acquire_or_None()
const noexcept
214 PyObject* result = this->p ?
reinterpret_cast<PyObject*
>(this->p) : Py_None;
219 explicit operator bool()
const noexcept
221 return this->p !=
nullptr;
224 bool operator!()
const noexcept
226 return this->p ==
nullptr;
229 Py_ssize_t REFCNT()
const noexcept
231 return p ? Py_REFCNT(p) : -42;
234 PyTypeObject* TYPE()
const noexcept
236 return p ? Py_TYPE(p) :
nullptr;
240 inline const std::string as_str()
const noexcept;
242 inline OwnedObject PyRequireAttr(
const char*
const name)
const;
254 void _set_raw_pointer(
void* t)
257 p =
reinterpret_cast<T*
>(t);
259 void* _get_raw_pointer()
const
265#ifdef GREENLET_USE_STDIO
266 template<
typename T, TypeChecker TC>
269 const std::type_info& t =
typeid(s);
271 <<
"(addr=" << s.borrow()
272 <<
", refcnt=" << s.REFCNT()
273 <<
", value=" << s.as_str()
280 template<
typename T, TypeChecker TC>
281 inline bool operator==(
const PyObjectPointer<T, TC>& lhs,
const PyObject*
const rhs)
noexcept
283 return static_cast<const void*
>(lhs.borrow_o()) ==
static_cast<const void*
>(rhs);
286 template<
typename T, TypeChecker TC,
typename X, TypeChecker XC>
287 inline bool operator==(
const PyObjectPointer<T, TC>& lhs,
const PyObjectPointer<X, XC>& rhs)
noexcept
289 return lhs.borrow_o() == rhs.borrow_o();
292 template<
typename T, TypeChecker TC,
typename X, TypeChecker XC>
293 inline bool operator!=(
const PyObjectPointer<T, TC>& lhs,
294 const PyObjectPointer<X, XC>& rhs)
noexcept
296 return lhs.borrow_o() != rhs.borrow_o();
299 template<
typename T=PyObject, TypeChecker TC=NoOpChecker>
322 Py_XINCREF(result.p);
332 T* op = other.borrow();
334 this->p = other.borrow();
359 const T* tmp = this->p;
367 return this->operator=(other.borrow());
382 template<
typename X, TypeChecker XC>
385 X* op = other.borrow();
387 return this->operator=(
reinterpret_cast<T*
>(op));
390 inline void steal(T* other)
392 assert(this->p ==
nullptr);
397 T* relinquish_ownership()
423 assert(this->p ==
nullptr);
428 void operator<<=(PyObject*& target,
OwnedObject& o)
430 target = o.relinquish_ownership();
458 void SetItem(
const char*
const key, PyObject* value)
460 Require(PyDict_SetItemString(this->p, key, value));
465 Require(PyDict_SetItem(this->p, key.borrow_o(), value));
469 template<
typename T=PyGreenlet, TypeChecker TC=GreenletChecker>
497 return this->operator=(other.borrow());
506 this->p =
reinterpret_cast<T*
>(owned);
516 T* relinquish_ownership()
523 PyObject* relinquish_ownership_o()
525 return reinterpret_cast<PyObject*
>(relinquish_ownership());
528 inline Greenlet* operator->()
const noexcept;
529 inline operator Greenlet*()
const noexcept;
532 template <
typename T=PyObject, TypeChecker TC=NoOpChecker>
558 template<
typename T=PyGreenlet, TypeChecker TC=GreenletChecker>
580 operator PyObject*()
const
582 return reinterpret_cast<PyObject*
>(this->p);
584 Greenlet* operator->()
const noexcept;
585 operator Greenlet*()
const noexcept;
590 template<
typename T, TypeChecker TC>
610 template<
typename T, TypeChecker TC>
613 return this->operator=(other.borrow());
638 assert(this->p ==
nullptr);
648 inline operator PyObject*()
const
661 ImmortalObject(str ? Require(PyUnicode_InternFromString(str)) :
nullptr)
669 this->p = Require(PyUnicode_InternFromString(str));
673 assert(this->str == str);
678 inline operator std::string()
const
702 ? Require(PyErr_NewException((
char*)name, base,
nullptr))
706 inline bool PyExceptionMatches()
const
708 return PyErr_ExceptionMatches(this->p) > 0;
713 template<
typename T, TypeChecker TC>
719 return OwnedObject::consuming(PyObject_Str(
reinterpret_cast<PyObject*
>(this->p)));
722 template<
typename T, TypeChecker TC>
723 inline const std::string PyObjectPointer<T, TC>::as_str() const noexcept
730 OwnedObject py_str = this->PyStr();
734 return PyUnicode_AsUTF8(py_str.borrow());
739 template<
typename T, TypeChecker TC>
740 inline OwnedObject PyObjectPointer<T, TC>::PyGetAttr(
const ImmortalObject& name)
const noexcept
743 return OwnedObject::consuming(PyObject_GetAttr(
reinterpret_cast<PyObject*
>(this->p), name));
746 template<
typename T, TypeChecker TC>
747 inline OwnedObject PyObjectPointer<T, TC>::PyRequireAttr(
const char*
const name)
const
750 return OwnedObject::consuming(Require(PyObject_GetAttrString(this->p, name), name));
753 template<
typename T, TypeChecker TC>
754 inline OwnedObject PyObjectPointer<T, TC>::PyRequireAttr(
const ImmortalString& name)
const
757 return OwnedObject::consuming(Require(
759 reinterpret_cast<PyObject*
>(this->p),
766 template<
typename T, TypeChecker TC>
767 inline OwnedObject PyObjectPointer<T, TC>::PyCall(
const BorrowedObject& arg)
const
769 return this->PyCall(arg.borrow());
772 template<
typename T, TypeChecker TC>
773 inline OwnedObject PyObjectPointer<T, TC>::PyCall(
PyGreenlet* arg)
const
775 return this->PyCall(
reinterpret_cast<PyObject*
>(arg));
778 template<
typename T, TypeChecker TC>
779 inline OwnedObject PyObjectPointer<T, TC>::PyCall(PyObject* arg)
const
782 return OwnedObject::consuming(PyObject_CallFunctionObjArgs(this->p, arg, NULL));
785 template<
typename T, TypeChecker TC>
786 inline OwnedObject PyObjectPointer<T, TC>::PyCall(
const BorrowedObject args,
787 const BorrowedObject kwargs)
const
790 return OwnedObject::consuming(PyObject_Call(this->p, args, kwargs));
793 template<
typename T, TypeChecker TC>
794 inline OwnedObject PyObjectPointer<T, TC>::PyCall(
const OwnedObject& args,
795 const OwnedObject& kwargs)
const
798 return OwnedObject::consuming(PyObject_Call(this->p, args.borrow(), kwargs.borrow()));
802 ListChecker(
void * p)
807 if (!PyList_Check(p)) {
808 throw TypeError(
"Expected a list");
825 if (other && PyList_Check(other.p)) {
828 PyObject* new_ptr = other.p;
842 inline bool empty()
const
844 return PyList_GET_SIZE(p) == 0;
847 inline Py_ssize_t size()
const
849 return PyList_GET_SIZE(p);
854 return PyList_GET_ITEM(p, index);
859 PyList_SetSlice(p, 0, PyList_GET_SIZE(p), NULL);
877 Require(PyModule_Create(&mod_def)))
887 void PyAddObject(
const char* name,
const long new_bool)
889 OwnedObject p = OwnedObject::consuming(Require(PyBool_FromLong(new_bool)));
890 this->PyAddObject(name, p);
893 void PyAddObject(
const char* name,
const OwnedObject& new_object)
898 this->PyAddObject(name, new_object.borrow());
901 void PyAddObject(
const char* name,
const ImmortalObject& new_object)
903 this->PyAddObject(name, new_object.borrow());
906 void PyAddObject(
const char* name, PyTypeObject& type)
908 this->PyAddObject(name,
reinterpret_cast<PyObject*
>(&type));
911 void PyAddObject(
const char* name, PyObject* new_object)
913 Py_INCREF(new_object);
915 Require(PyModule_AddObject(this->p, name, new_object));
938 PyObject** operator&()
946 operator PyObject**()
954 inline PyObject* relinquish_ownership()
956 PyObject* result = this->p;
978 PyObject** operator&()
983 inline operator PyObject*()
const
988 operator PyTypeObject*()
const
990 return reinterpret_cast<PyTypeObject*
>(this->p);
1004 PyErrPieces(PyObject* t, PyObject* v, PyObject* tb) :
1020 PyErr_Fetch(&t, &v, &tb);
1021 type.steal(t.relinquish_ownership());
1022 instance.steal(v.relinquish_ownership());
1023 traceback.steal(tb.relinquish_ownership());
1029 assert(!this->restored);
1030 this->restored =
true;
1032 this->type.relinquish_ownership(),
1033 this->instance.relinquish_ownership(),
1034 this->traceback.relinquish_ownership());
1035 assert(!this->type && !this->instance && !this->traceback);
1043 if (traceback.is_None()) {
1044 traceback =
nullptr;
1047 if (traceback && !PyTraceBack_Check(traceback.borrow())) {
1049 "throw() third argument must be a traceback object");
1052 if (PyExceptionClass_Check(type)) {
1059 PyErr_NormalizeException(&type, &instance, &traceback);
1062 else if (PyExceptionInstance_Check(type)) {
1067 if (instance && !instance.is_None()) {
1070 "instance exception may not have a separate value");
1073 this->instance = this->type;
1074 this->type = PyExceptionInstance_Class(instance.borrow());
1092 PyErr_Format(PyExc_TypeError,
1093 "exceptions must be classes, or instances, not %s",
1094 Py_TYPE(type.borrow())->tp_name);
1110 inline PyObject** operator&()
Definition TGreenlet.hpp:343
Definition greenlet_exceptions.hpp:17
Definition greenlet_refs.hpp:600
Definition greenlet_refs.hpp:534
Definition greenlet_refs.hpp:872
Definition greenlet_refs.hpp:686
Definition greenlet_refs.hpp:695
Definition greenlet_refs.hpp:618
ImmortalObject & operator=(PyObject *it)
Definition greenlet_refs.hpp:636
Definition greenlet_refs.hpp:655
Definition greenlet_refs.hpp:447
Definition greenlet_refs.hpp:435
Definition greenlet_refs.hpp:968
Definition greenlet_refs.hpp:813
Definition greenlet_refs.hpp:301
Definition greenlet_refs.hpp:1102
Definition greenlet_refs.hpp:925
Definition greenlet_refs.hpp:995
Definition greenlet_refs.hpp:171
Definition greenlet_refs.hpp:560
Definition greenlet_refs.hpp:471