Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
TThreadStateCreator.hpp106 linesDownload Raw Back to greenlet
1#ifndef GREENLET_THREAD_STATE_CREATOR_HPP
2#define GREENLET_THREAD_STATE_CREATOR_HPP
3
4#include <ctime>
5#include <stdexcept>
6
7#include "greenlet_internal.hpp"
8#include "greenlet_refs.hpp"
9#include "greenlet_thread_support.hpp"
10
11#include "TThreadState.hpp"
12
13namespace greenlet {
14
15
16typedef void (*ThreadStateDestructor)(ThreadState* const);
17
18// Only one of these, auto created per thread as a thread_local.
19// This means we don't have to worry about atomic access to the
20// internals, because by definition all access is happening on a
21// single thread.
22// Constructing the state constructs the MainGreenlet.
23template<ThreadStateDestructor Destructor>
24class ThreadStateCreator
25{
26private:
27    // Initialized to 1, and, if still 1, created on access.
28    // Set to 0 on destruction.
29    ThreadState* _state;
30    G_NO_COPIES_OF_CLS(ThreadStateCreator);
31
32    inline bool has_initialized_state() const noexcept
33    {
34        return this->_state != (ThreadState*)1;
35    }
36
37    inline bool has_state() const noexcept
38    {
39        return this->has_initialized_state() && this->_state != nullptr;
40    }
41
42public:
43
44    ThreadStateCreator() :
45        _state((ThreadState*)1)
46    {
47    }
48
49    ~ThreadStateCreator()
50    {
51        if (this->has_state()) {
52            Destructor(this->_state);
53        }
54
55        this->_state = nullptr;
56    }
57
58    inline ThreadState& state()
59    {
60        // The main greenlet will own this pointer when it is created,
61        // which will be right after this. The plan is to give every
62        // greenlet a pointer to the main greenlet for the thread it
63        // runs in; if we are doing something cross-thread, we need to
64        // access the pointer from the main greenlet. Deleting the
65        // thread, and hence the thread-local storage, will delete the
66        // state pointer in the main greenlet.
67        if (!this->has_initialized_state()) {
68            // XXX: Assuming allocation never fails
69            this->_state = new ThreadState;
70            // For non-standard threading, we need to store an object
71            // in the Python thread state dictionary so that it can be
72            // DECREF'd when the thread ends (ideally; the dict could
73            // last longer) and clean this object up.
74        }
75        if (!this->_state) {
76            throw std::runtime_error("Accessing state after destruction.");
77        }
78        return *this->_state;
79    }
80
81    operator ThreadState&()
82    {
83        return this->state();
84    }
85
86    operator ThreadState*()
87    {
88        return &this->state();
89    }
90
91    inline int tp_traverse(visitproc visit, void* arg)
92    {
93        if (this->has_state()) {
94            return this->_state->tp_traverse(visit, arg);
95        }
96        return 0;
97    }
98
99};
100
101
102
103}; // namespace greenlet
104
105#endif
106 
codekingpro/portable-devtools · Team Ai