123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
- /**
- * Implementation of greenlet::MainGreenlet.
- *
- * Format with:
- * clang-format -i --style=file src/greenlet/greenlet.c
- *
- *
- * Fix missing braces with:
- * clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
- */
- #ifndef T_MAIN_GREENLET_CPP
- #define T_MAIN_GREENLET_CPP
- #include "TGreenlet.hpp"
- // Protected by the GIL. Incremented when we create a main greenlet,
- // in a new thread, decremented when it is destroyed.
- static Py_ssize_t G_TOTAL_MAIN_GREENLETS;
- namespace greenlet {
- greenlet::PythonAllocator<MainGreenlet> MainGreenlet::allocator;
- void* MainGreenlet::operator new(size_t UNUSED(count))
- {
- return allocator.allocate(1);
- }
- void MainGreenlet::operator delete(void* ptr)
- {
- return allocator.deallocate(static_cast<MainGreenlet*>(ptr),
- 1);
- }
- MainGreenlet::MainGreenlet(PyGreenlet* p, ThreadState* state)
- : Greenlet(p, StackState::make_main()),
- _self(p),
- _thread_state(state)
- {
- G_TOTAL_MAIN_GREENLETS++;
- }
- MainGreenlet::~MainGreenlet()
- {
- G_TOTAL_MAIN_GREENLETS--;
- this->tp_clear();
- }
- ThreadState*
- MainGreenlet::thread_state() const noexcept
- {
- return this->_thread_state;
- }
- void
- MainGreenlet::thread_state(ThreadState* t) noexcept
- {
- assert(!t);
- this->_thread_state = t;
- }
- const BorrowedMainGreenlet
- MainGreenlet::main_greenlet() const
- {
- return this->_self;
- }
- BorrowedMainGreenlet
- MainGreenlet::find_main_greenlet_in_lineage() const
- {
- return BorrowedMainGreenlet(this->_self);
- }
- bool
- MainGreenlet::was_running_in_dead_thread() const noexcept
- {
- return !this->_thread_state;
- }
- OwnedObject
- MainGreenlet::g_switch()
- {
- try {
- this->check_switch_allowed();
- }
- catch (const PyErrOccurred&) {
- this->release_args();
- throw;
- }
- switchstack_result_t err = this->g_switchstack();
- if (err.status < 0) {
- // XXX: This code path is untested, but it is shared
- // with the UserGreenlet path that is tested.
- return this->on_switchstack_or_initialstub_failure(
- this,
- err,
- true, // target was me
- false // was initial stub
- );
- }
- return err.the_new_current_greenlet->g_switch_finish(err);
- }
- int
- MainGreenlet::tp_traverse(visitproc visit, void* arg)
- {
- if (this->_thread_state) {
- // we've already traversed main, (self), don't do it again.
- int result = this->_thread_state->tp_traverse(visit, arg, false);
- if (result) {
- return result;
- }
- }
- return Greenlet::tp_traverse(visit, arg);
- }
- const OwnedObject&
- MainGreenlet::run() const
- {
- throw AttributeError("Main greenlets do not have a run attribute.");
- }
- void
- MainGreenlet::run(const BorrowedObject UNUSED(nrun))
- {
- throw AttributeError("Main greenlets do not have a run attribute.");
- }
- void
- MainGreenlet::parent(const BorrowedObject raw_new_parent)
- {
- if (!raw_new_parent) {
- throw AttributeError("can't delete attribute");
- }
- throw AttributeError("cannot set the parent of a main greenlet");
- }
- const OwnedGreenlet
- MainGreenlet::parent() const
- {
- return OwnedGreenlet(); // null becomes None
- }
- }; // namespace greenlet
- #endif
|