12#ifndef T_USER_GREENLET_CPP
13#define T_USER_GREENLET_CPP
15#include "greenlet_internal.hpp"
16#include "TGreenlet.hpp"
18#include "TThreadStateDestroy.cpp"
25void* UserGreenlet::operator
new(
size_t UNUSED(count))
27 return allocator.allocate(1);
31void UserGreenlet::operator
delete(
void* ptr)
33 return allocator.deallocate(
static_cast<UserGreenlet*
>(ptr),
38UserGreenlet::UserGreenlet(
PyGreenlet* p, BorrowedGreenlet the_parent)
39 : Greenlet(p), _parent(the_parent)
43UserGreenlet::~UserGreenlet()
48 this->python_state.did_finish(
nullptr);
54UserGreenlet::main_greenlet()
const
56 return this->_main_greenlet;
61UserGreenlet::find_main_greenlet_in_lineage()
const
63 if (this->started()) {
64 assert(this->_main_greenlet);
74 return this->_parent->find_main_greenlet_in_lineage();
83UserGreenlet::throw_GreenletExit_during_dealloc(
const ThreadState& current_thread_state)
94 return Greenlet::throw_GreenletExit_during_dealloc(current_thread_state);
98UserGreenlet::thread_state() const noexcept
104 if (!this->_main_greenlet) {
107 return this->_main_greenlet->thread_state();
112UserGreenlet::was_running_in_dead_thread() const noexcept
114 return this->_main_greenlet && !this->thread_state();
118UserGreenlet::g_switch()
120 assert(this->args() || PyErr_Occurred());
123 this->check_switch_allowed();
125 catch (
const PyErrOccurred&) {
126 this->release_args();
139 switchstack_result_t err;
140 Greenlet* target =
this;
147 bool target_was_me =
true;
148 bool was_initial_stub =
false;
150 if (target->active()) {
151 if (!target_was_me) {
152 target->args() <<= this->args();
153 assert(!this->args());
155 err = target->g_switchstack();
158 if (!target->started()) {
160 assert(!target->main());
161 UserGreenlet* real_target =
static_cast<UserGreenlet*
>(target);
164 was_initial_stub =
true;
165 if (!target_was_me) {
166 target->args() <<= this->args();
167 assert(!this->args());
173 err = real_target->g_initialstub(&dummymarker);
175 catch (
const PyErrOccurred&) {
176 this->release_args();
179 catch (
const GreenletStartedWhileInPython&) {
191 target = target->parent();
192 target_was_me =
false;
200 if (err.status < 0) {
205 return this->on_switchstack_or_initialstub_failure(target, err, target_was_me, was_initial_stub);
210 return err.the_new_current_greenlet->g_switch_finish(err);
215Greenlet::switchstack_result_t
216UserGreenlet::g_initialstub(
void* mark)
226 SwitchingArgs args(this->args());
235 run = this->self().PyRequireAttr(mod_globs->str_run);
237 saved.PyErrRestore();
241 this->check_switch_allowed();
250 if (this->stack_state.started()) {
254 assert(!this->args());
255 this->args() <<= args;
256 throw GreenletStartedWhileInPython();
266#if GREENLET_USE_CFRAME
274 _PyCFrame trace_info;
276 this->python_state.set_new_cframe(trace_info);
279 ThreadState& thread_state = GET_THREAD_STATE().state();
280 this->stack_state = StackState(mark,
281 thread_state.borrow_current()->stack_state);
282 this->python_state.set_initial_state(PyThreadState_GET());
283 this->exception_state.clear();
284 this->_main_greenlet = thread_state.get_main_greenlet();
287 switchstack_result_t err = this->g_switchstack();
298 if (err.status == 1) {
305 this->inner_bootstrap(err.origin_greenlet.relinquish_ownership(),
306 run.relinquish_ownership());
324 catch (
const std::exception& e) {
325 std::string base =
"greenlet: Unhandled C++ exception: ";
327 Py_FatalError(base.c_str());
343 "greenlet: inner_bootstrap threw unknown exception; "
344 "is the process terminating?\n");
348 Py_FatalError(
"greenlet: inner_bootstrap returned with no exception.\n");
360 if (err.status < 0) {
362 this->stack_state = StackState();
363 this->_main_greenlet.CLEAR();
372 run.relinquish_ownership();
379UserGreenlet::inner_bootstrap(
PyGreenlet* origin_greenlet, PyObject* run)
391 assert(this->thread_state()->borrow_current() == BorrowedGreenlet(this->_self));
400 this->thread_state()->restore_exception_state();
404 this->stack_state.set_active();
410 args <<= this->args();
411 assert(!this->args());
417 this->_run_callable.CLEAR();
423 if (OwnedObject tracefunc = this->thread_state()->get_tracefunc()) {
424 OwnedGreenlet trace_origin;
425 trace_origin = origin_greenlet;
427 g_calltrace(tracefunc,
428 args ? mod_globs->event_switch : mod_globs->event_throw,
432 catch (
const PyErrOccurred&) {
443 Py_CLEAR(origin_greenlet);
458 result = OwnedObject::consuming(PyObject_Call(run, args.args().borrow(), args.kwargs().borrow()));
496# if defined(WIN32) || defined(_WIN32)
498 "greenlet: Unhandled C++ exception from a greenlet run function. "
499 "Because memory is likely corrupted, terminating process.");
511 && mod_globs->PyExc_GreenletExit.PyExceptionMatches()
517 result <<= this->args();
518 result = single_result(result);
520 this->release_args();
521 this->python_state.did_finish(PyThreadState_GET());
523 result = g_handle_exit(result);
524 assert(this->thread_state()->borrow_current() == this->_self);
527 this->stack_state.set_inactive();
532 for (Greenlet* parent = this->_parent;
534 parent = parent->parent()) {
541 parent->args() <<= result;
547 result = parent->g_switch();
549 catch (
const PyErrOccurred&) {
560 PyErr_WriteUnraisable(this->self().borrow_o());
561 Py_FatalError(
"greenlet: ran out of parent greenlets while propagating exception; "
567UserGreenlet::run(
const BorrowedObject nrun)
569 if (this->started()) {
570 throw AttributeError(
572 "after the start of the greenlet");
574 this->_run_callable = nrun;
578UserGreenlet::parent()
const
580 return this->_parent;
584UserGreenlet::parent(
const BorrowedObject raw_new_parent)
586 if (!raw_new_parent) {
587 throw AttributeError(
"can't delete attribute");
591 BorrowedGreenlet new_parent(raw_new_parent.borrow());
594 for (BorrowedGreenlet p = new_parent; p; p = p->parent()) {
595 if (p == this->self()) {
596 throw ValueError(
"cyclic parent chain");
598 main_greenlet_of_new_parent = p->main_greenlet();
601 if (!main_greenlet_of_new_parent) {
602 throw ValueError(
"parent must not be garbage collected");
606 && this->_main_greenlet != main_greenlet_of_new_parent) {
607 throw ValueError(
"parent cannot be on a different thread");
610 this->_parent = new_parent;
614UserGreenlet::murder_in_place()
616 this->_main_greenlet.CLEAR();
617 Greenlet::murder_in_place();
621UserGreenlet::belongs_to_thread(
const ThreadState* thread_state)
const
623 return Greenlet::belongs_to_thread(thread_state) && this->_main_greenlet == thread_state->borrow_main_greenlet();
628UserGreenlet::tp_traverse(visitproc visit,
void* arg)
630 Py_VISIT(this->_parent.borrow_o());
631 Py_VISIT(this->_main_greenlet.borrow_o());
632 Py_VISIT(this->_run_callable.borrow_o());
634 return Greenlet::tp_traverse(visit, arg);
638UserGreenlet::tp_clear()
640 Greenlet::tp_clear();
641 this->_parent.CLEAR();
642 this->_main_greenlet.CLEAR();
643 this->_run_callable.CLEAR();
647UserGreenlet::ParentIsCurrentGuard::ParentIsCurrentGuard(UserGreenlet* p,
648 const ThreadState& thread_state)
649 : oldparent(p->_parent),
652 p->_parent = thread_state.get_current();
655UserGreenlet::ParentIsCurrentGuard::~ParentIsCurrentGuard()
657 this->
greenlet->_parent = oldparent;
Definition TThreadState.hpp:87
Definition TGreenlet.hpp:711
Definition greenlet_refs.hpp:600
Definition greenlet_refs.hpp:995
Definition greenlet_allocator.hpp:17