|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <cstdlib> |
|
#include <string> |
|
#include <algorithm> |
|
#include <exception> |
|
|
|
|
|
#define PY_SSIZE_T_CLEAN |
|
#include <Python.h> |
|
#include "structmember.h" |
|
|
|
#include "greenlet_internal.hpp" |
|
|
|
|
|
|
|
#include "greenlet_refs.hpp" |
|
#include "greenlet_slp_switch.hpp" |
|
|
|
#include "greenlet_thread_support.hpp" |
|
#include "TGreenlet.hpp" |
|
|
|
#include "TGreenletGlobals.cpp" |
|
|
|
#include "TGreenlet.cpp" |
|
#include "TMainGreenlet.cpp" |
|
#include "TUserGreenlet.cpp" |
|
#include "TBrokenGreenlet.cpp" |
|
#include "TExceptionState.cpp" |
|
#include "TPythonState.cpp" |
|
#include "TStackState.cpp" |
|
|
|
#include "TThreadState.hpp" |
|
#include "TThreadStateCreator.hpp" |
|
#include "TThreadStateDestroy.cpp" |
|
|
|
#include "PyGreenlet.cpp" |
|
#include "PyGreenletUnswitchable.cpp" |
|
#include "CObjects.cpp" |
|
|
|
using greenlet::LockGuard; |
|
using greenlet::LockInitError; |
|
using greenlet::PyErrOccurred; |
|
using greenlet::Require; |
|
|
|
using greenlet::g_handle_exit; |
|
using greenlet::single_result; |
|
|
|
using greenlet::Greenlet; |
|
using greenlet::UserGreenlet; |
|
using greenlet::MainGreenlet; |
|
using greenlet::BrokenGreenlet; |
|
using greenlet::ThreadState; |
|
using greenlet::PythonState; |
|
|
|
|
|
|
|
|
|
template<typename T, greenlet::refs::TypeChecker TC> |
|
greenlet::refs::_BorrowedGreenlet<T, TC>& greenlet::refs::_BorrowedGreenlet<T, TC>::operator=(const greenlet::refs::BorrowedObject& other) |
|
{ |
|
this->_set_raw_pointer(static_cast<PyObject*>(other)); |
|
return *this; |
|
} |
|
|
|
template <typename T, greenlet::refs::TypeChecker TC> |
|
inline greenlet::refs::_BorrowedGreenlet<T, TC>::operator Greenlet*() const noexcept |
|
{ |
|
if (!this->p) { |
|
return nullptr; |
|
} |
|
return reinterpret_cast<PyGreenlet*>(this->p)->pimpl; |
|
} |
|
|
|
template<typename T, greenlet::refs::TypeChecker TC> |
|
greenlet::refs::_BorrowedGreenlet<T, TC>::_BorrowedGreenlet(const BorrowedObject& p) |
|
: BorrowedReference<T, TC>(nullptr) |
|
{ |
|
|
|
this->_set_raw_pointer(p.borrow()); |
|
} |
|
|
|
template <typename T, greenlet::refs::TypeChecker TC> |
|
inline greenlet::refs::_OwnedGreenlet<T, TC>::operator Greenlet*() const noexcept |
|
{ |
|
if (!this->p) { |
|
return nullptr; |
|
} |
|
return reinterpret_cast<PyGreenlet*>(this->p)->pimpl; |
|
} |
|
|
|
|
|
|
|
#ifdef __clang__ |
|
# pragma clang diagnostic push |
|
# pragma clang diagnostic ignored "-Wmissing-field-initializers" |
|
# pragma clang diagnostic ignored "-Wwritable-strings" |
|
#elif defined(__GNUC__) |
|
# pragma GCC diagnostic push |
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wwrite-strings" |
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" { |
|
static int GREENLET_NOINLINE(slp_save_state_trampoline)(char* stackref) |
|
{ |
|
return switching_thread_state->slp_save_state(stackref); |
|
} |
|
static void GREENLET_NOINLINE(slp_restore_state_trampoline)() |
|
{ |
|
switching_thread_state->slp_restore_state(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
#include "PyModule.cpp" |
|
|
|
|
|
|
|
static PyObject* |
|
greenlet_internal_mod_init() noexcept |
|
{ |
|
static void* _PyGreenlet_API[PyGreenlet_API_pointers]; |
|
|
|
try { |
|
CreatedModule m(greenlet_module_def); |
|
|
|
Require(PyType_Ready(&PyGreenlet_Type)); |
|
Require(PyType_Ready(&PyGreenletUnswitchable_Type)); |
|
|
|
mod_globs = new greenlet::GreenletGlobals; |
|
ThreadState::init(); |
|
|
|
m.PyAddObject("greenlet", PyGreenlet_Type); |
|
m.PyAddObject("UnswitchableGreenlet", PyGreenletUnswitchable_Type); |
|
m.PyAddObject("error", mod_globs->PyExc_GreenletError); |
|
m.PyAddObject("GreenletExit", mod_globs->PyExc_GreenletExit); |
|
|
|
m.PyAddObject("GREENLET_USE_GC", 1); |
|
m.PyAddObject("GREENLET_USE_TRACING", 1); |
|
m.PyAddObject("GREENLET_USE_CONTEXT_VARS", 1L); |
|
m.PyAddObject("GREENLET_USE_STANDARD_THREADING", 1L); |
|
|
|
OwnedObject clocks_per_sec = OwnedObject::consuming(PyLong_FromSsize_t(CLOCKS_PER_SEC)); |
|
m.PyAddObject("CLOCKS_PER_SEC", clocks_per_sec); |
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const char* const* p = copy_on_greentype; *p; p++) { |
|
OwnedObject o = m.PyRequireAttr(*p); |
|
PyDict_SetItemString(PyGreenlet_Type.tp_dict, *p, o.borrow()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
_PyGreenlet_API[PyGreenlet_Type_NUM] = (void*)&PyGreenlet_Type; |
|
|
|
|
|
_PyGreenlet_API[PyExc_GreenletError_NUM] = (void*)mod_globs->PyExc_GreenletError; |
|
_PyGreenlet_API[PyExc_GreenletExit_NUM] = (void*)mod_globs->PyExc_GreenletExit; |
|
|
|
|
|
_PyGreenlet_API[PyGreenlet_New_NUM] = (void*)PyGreenlet_New; |
|
_PyGreenlet_API[PyGreenlet_GetCurrent_NUM] = (void*)PyGreenlet_GetCurrent; |
|
_PyGreenlet_API[PyGreenlet_Throw_NUM] = (void*)PyGreenlet_Throw; |
|
_PyGreenlet_API[PyGreenlet_Switch_NUM] = (void*)PyGreenlet_Switch; |
|
_PyGreenlet_API[PyGreenlet_SetParent_NUM] = (void*)PyGreenlet_SetParent; |
|
|
|
|
|
_PyGreenlet_API[PyGreenlet_MAIN_NUM] = (void*)Extern_PyGreenlet_MAIN; |
|
_PyGreenlet_API[PyGreenlet_STARTED_NUM] = (void*)Extern_PyGreenlet_STARTED; |
|
_PyGreenlet_API[PyGreenlet_ACTIVE_NUM] = (void*)Extern_PyGreenlet_ACTIVE; |
|
_PyGreenlet_API[PyGreenlet_GET_PARENT_NUM] = (void*)Extern_PyGreenlet_GET_PARENT; |
|
|
|
|
|
|
|
|
|
|
|
const NewReference c_api_object(Require( |
|
PyCapsule_New( |
|
(void*)_PyGreenlet_API, |
|
"greenlet._C_API", |
|
NULL))); |
|
m.PyAddObject("_C_API", c_api_object); |
|
assert(c_api_object.REFCNT() == 2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return m.borrow(); |
|
} |
|
catch (const LockInitError& e) { |
|
PyErr_SetString(PyExc_MemoryError, e.what()); |
|
return NULL; |
|
} |
|
catch (const PyErrOccurred&) { |
|
return NULL; |
|
} |
|
|
|
} |
|
|
|
extern "C" { |
|
|
|
PyMODINIT_FUNC |
|
PyInit__greenlet(void) |
|
{ |
|
return greenlet_internal_mod_init(); |
|
} |
|
|
|
}; |
|
|
|
#ifdef __clang__ |
|
# pragma clang diagnostic pop |
|
#elif defined(__GNUC__) |
|
# pragma GCC diagnostic pop |
|
#endif |
|
|