95 OwnedMainGreenlet main_greenlet;
98 OwnedGreenlet current_greenlet;
101 OwnedObject tracefunc;
103 typedef std::vector<PyGreenlet*, PythonAllocator<PyGreenlet*> > deleteme_t;
113#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
114 void* exception_state;
117#ifdef Py_GIL_DISABLED
118 static std::atomic<std::clock_t> _clocks_used_doing_gc;
120 static std::clock_t _clocks_used_doing_gc;
135 gmain =
reinterpret_cast<PyGreenlet*
>(PyType_GenericAlloc(&PyGreenlet_Type, 0));
142 assert(Py_REFCNT(gmain) == 1);
143 assert(gmain->pimpl == main);
149 static void*
operator new(
size_t UNUSED(count))
151 return ThreadState::allocator.allocate(1);
154 static void operator delete(
void* ptr)
156 return ThreadState::allocator.deallocate(
static_cast<ThreadState*
>(ptr),
162 ThreadState::get_referrers_name =
"get_referrers";
163 ThreadState::set_clocks_used_doing_gc(0);
169#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
170 this->exception_state = slp_get_exception_state();
176 this->main_greenlet = OwnedMainGreenlet::consuming(
179 assert(this->main_greenlet);
180 this->current_greenlet = main->self();
183 assert(this->main_greenlet.REFCNT() == 2);
186 inline void restore_exception_state()
188#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED
191 slp_set_exception_state(this->exception_state);
195 inline bool has_main_greenlet()
const noexcept
197 return bool(this->main_greenlet);
205 int tp_traverse(visitproc visit,
void* arg,
bool traverse_main=
true)
208 Py_VISIT(main_greenlet.borrow_o());
210 if (traverse_main || current_greenlet != main_greenlet) {
211 Py_VISIT(current_greenlet.borrow_o());
213 Py_VISIT(tracefunc.borrow());
219 assert(this->main_greenlet);
220 assert(this->main_greenlet.REFCNT() >= 2);
221 return this->main_greenlet;
224 inline OwnedMainGreenlet get_main_greenlet()
const noexcept
226 return this->main_greenlet;
237 this->clear_deleteme_list();
240 return this->current_greenlet;
248 this->clear_deleteme_list();
249 return this->current_greenlet;
257 return this->current_greenlet;
260 template<
typename T, refs::TypeChecker TC>
263 return this->current_greenlet.borrow_o() == obj.borrow_o();
266 inline void set_current(
const OwnedGreenlet& target)
268 this->current_greenlet = target;
283 inline void clear_deleteme_list(
const bool murder=
false)
285 if (!this->deleteme.empty()) {
289 deleteme_t copy = this->deleteme;
290 this->deleteme.clear();
291 for(deleteme_t::iterator it = copy.begin(), end = copy.end();
298 to_del->pimpl->murder_in_place();
308 if (PyErr_Occurred()) {
309 PyErr_WriteUnraisable(
nullptr);
327 inline void set_tracefunc(BorrowedObject tracefunc)
330 if (tracefunc == BorrowedObject(Py_None)) {
331 this->tracefunc.CLEAR();
334 this->tracefunc = tracefunc;
346 this->deleteme.push_back(to_del);
354#ifdef Py_GIL_DISABLED
355 return ThreadState::_clocks_used_doing_gc.load(std::memory_order_relaxed);
357 return ThreadState::_clocks_used_doing_gc;
361 inline static void set_clocks_used_doing_gc(std::clock_t value)
363#ifdef Py_GIL_DISABLED
364 ThreadState::_clocks_used_doing_gc.store(value, std::memory_order_relaxed);
366 ThreadState::_clocks_used_doing_gc = value;
370 inline static void add_clocks_used_doing_gc(std::clock_t value)
372#ifdef Py_GIL_DISABLED
373 ThreadState::_clocks_used_doing_gc.fetch_add(value, std::memory_order_relaxed);
375 ThreadState::_clocks_used_doing_gc += value;
381 if (!PyInterpreterState_Head()) {
392 this->tracefunc.CLEAR();
395 this->clear_deleteme_list(
true);
398 assert(this->main_greenlet->thread_state() ==
nullptr);
405 if (this->current_greenlet == this->main_greenlet && this->current_greenlet) {
406 assert(this->current_greenlet->is_currently_running_in_some_thread());
408 this->current_greenlet.CLEAR();
409 assert(!this->current_greenlet);
412 PyGreenlet* old_main_greenlet = this->main_greenlet.borrow();
413 Py_ssize_t cnt = this->main_greenlet.REFCNT();
414 this->main_greenlet.CLEAR();
416 && cnt == 2 && Py_REFCNT(old_main_greenlet) == 1) {
422 std::clock_t begin = std::clock();
425 OwnedObject get_referrers = gc.PyRequireAttr(ThreadState::get_referrers_name);
426 OwnedList refs(get_referrers.PyCall(old_main_greenlet));
427 if (refs && refs.empty()) {
428 assert(refs.REFCNT() == 1);
438 Py_DECREF(old_main_greenlet);
442 && PyCFunction_Check(refs.at(0))
443 && Py_REFCNT(refs.at(0)) == 2) {
444 assert(refs.REFCNT() == 1);
453 if (PyCFunction_GetFunction(refs.at(0).borrow()) == (PyCFunction)green_switch) {
454 BorrowedObject function_w = refs.at(0);
459 assert(function_w.REFCNT() == 1);
460 refs = get_referrers.PyCall(function_w);
461 if (refs && refs.empty()) {
464 Py_CLEAR(function_w);
468 std::clock_t end = std::clock();
469 ThreadState::add_clocks_used_doing_gc(end - begin);
478 if (this->current_greenlet) {
479 this->current_greenlet->murder_in_place();
480 this->current_greenlet.CLEAR();
483 if (this->main_greenlet) {
497 this->main_greenlet.CLEAR();
500 if (PyErr_Occurred()) {
501 PyErr_WriteUnraisable(NULL);