about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/greenlet/TThreadStateCreator.hpp
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/greenlet/TThreadStateCreator.hpp')
-rw-r--r--.venv/lib/python3.12/site-packages/greenlet/TThreadStateCreator.hpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/greenlet/TThreadStateCreator.hpp b/.venv/lib/python3.12/site-packages/greenlet/TThreadStateCreator.hpp
new file mode 100644
index 00000000..2ec7ab55
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/greenlet/TThreadStateCreator.hpp
@@ -0,0 +1,102 @@
+#ifndef GREENLET_THREAD_STATE_CREATOR_HPP
+#define GREENLET_THREAD_STATE_CREATOR_HPP
+
+#include <ctime>
+#include <stdexcept>
+
+#include "greenlet_internal.hpp"
+#include "greenlet_refs.hpp"
+#include "greenlet_thread_support.hpp"
+
+#include "TThreadState.hpp"
+
+namespace greenlet {
+
+
+typedef void (*ThreadStateDestructor)(ThreadState* const);
+
+template<ThreadStateDestructor Destructor>
+class ThreadStateCreator
+{
+private:
+    // Initialized to 1, and, if still 1, created on access.
+    // Set to 0 on destruction.
+    ThreadState* _state;
+    G_NO_COPIES_OF_CLS(ThreadStateCreator);
+
+    inline bool has_initialized_state() const noexcept
+    {
+        return this->_state != (ThreadState*)1;
+    }
+
+    inline bool has_state() const noexcept
+    {
+        return this->has_initialized_state() && this->_state != nullptr;
+    }
+
+public:
+
+    // Only one of these, auto created per thread.
+    // Constructing the state constructs the MainGreenlet.
+    ThreadStateCreator() :
+        _state((ThreadState*)1)
+    {
+    }
+
+    ~ThreadStateCreator()
+    {
+        if (this->has_state()) {
+            Destructor(this->_state);
+        }
+
+        this->_state = nullptr;
+    }
+
+    inline ThreadState& state()
+    {
+        // The main greenlet will own this pointer when it is created,
+        // which will be right after this. The plan is to give every
+        // greenlet a pointer to the main greenlet for the thread it
+        // runs in; if we are doing something cross-thread, we need to
+        // access the pointer from the main greenlet. Deleting the
+        // thread, and hence the thread-local storage, will delete the
+        // state pointer in the main greenlet.
+        if (!this->has_initialized_state()) {
+            // XXX: Assuming allocation never fails
+            this->_state = new ThreadState;
+            // For non-standard threading, we need to store an object
+            // in the Python thread state dictionary so that it can be
+            // DECREF'd when the thread ends (ideally; the dict could
+            // last longer) and clean this object up.
+        }
+        if (!this->_state) {
+            throw std::runtime_error("Accessing state after destruction.");
+        }
+        return *this->_state;
+    }
+
+    operator ThreadState&()
+    {
+        return this->state();
+    }
+
+    operator ThreadState*()
+    {
+        return &this->state();
+    }
+
+    inline int tp_traverse(visitproc visit, void* arg)
+    {
+        if (this->has_state()) {
+            return this->_state->tp_traverse(visit, arg);
+        }
+        return 0;
+    }
+
+};
+
+
+
+}; // namespace greenlet
+
+#endif