Qucs-S S-parameter Viewer & RF Synthesis Tools
Loading...
Searching...
No Matches
TGreenletGlobals.cpp
1/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
12#ifndef T_GREENLET_GLOBALS
13#define T_GREENLET_GLOBALS
14
15#include "greenlet_refs.hpp"
16#include "greenlet_exceptions.hpp"
17#include "greenlet_thread_support.hpp"
18#include "greenlet_internal.hpp"
19
20namespace greenlet {
21
22// This encapsulates what were previously module global "constants"
23// established at init time.
24// This is a step towards Python3 style module state that allows
25// reloading.
26//
27// In an earlier iteration of this code, we used placement new to be
28// able to allocate this object statically still, so that references
29// to its members don't incur an extra pointer indirection.
30// But under some scenarios, that could result in crashes at
31// shutdown because apparently the destructor was getting run twice?
33{
34
35public:
36 const greenlet::refs::ImmortalEventName event_switch;
37 const greenlet::refs::ImmortalEventName event_throw;
38 const greenlet::refs::ImmortalException PyExc_GreenletError;
39 const greenlet::refs::ImmortalException PyExc_GreenletExit;
40 const greenlet::refs::ImmortalObject empty_tuple;
41 const greenlet::refs::ImmortalObject empty_dict;
43 Mutex* const thread_states_to_destroy_lock;
44 greenlet::cleanup_queue_t thread_states_to_destroy;
45
47 event_switch("switch"),
48 event_throw("throw"),
49 PyExc_GreenletError("greenlet.error"),
50 PyExc_GreenletExit("greenlet.GreenletExit", PyExc_BaseException),
51 empty_tuple(Require(PyTuple_New(0))),
52 empty_dict(Require(PyDict_New())),
53 str_run("run"),
54 thread_states_to_destroy_lock(new Mutex())
55 {}
56
58 {
59 // This object is (currently) effectively immortal, and not
60 // just because of those placement new tricks; if we try to
61 // deallocate the static object we allocated, and overwrote,
62 // we would be doing so at C++ teardown time, which is after
63 // the final Python GIL is released, and we can't use the API
64 // then.
65 // (The members will still be destructed, but they also don't
66 // do any deallocation.)
67 }
68
69 void queue_to_destroy(ThreadState* ts) const
70 {
71 // we're currently accessed through a static const object,
72 // implicitly marking our members as const, so code can't just
73 // call push_back (or pop_back) without casting away the
74 // const.
75 //
76 // Do that for callers.
77 greenlet::cleanup_queue_t& q = const_cast<greenlet::cleanup_queue_t&>(this->thread_states_to_destroy);
78 q.push_back(ts);
79 }
80
81 ThreadState* take_next_to_destroy() const
82 {
83 greenlet::cleanup_queue_t& q = const_cast<greenlet::cleanup_queue_t&>(this->thread_states_to_destroy);
84 ThreadState* result = q.back();
85 q.pop_back();
86 return result;
87 }
88};
89
90}; // namespace greenlet
91
92static const greenlet::GreenletGlobals* mod_globs;
93
94#endif // T_GREENLET_GLOBALS
Definition TGreenletGlobals.cpp:33
Definition TThreadState.hpp:87
Definition greenlet_refs.hpp:686
Definition greenlet_refs.hpp:695
Definition greenlet_refs.hpp:618
Definition greenlet_refs.hpp:655
Definition __init__.py:1