Qucs-S S-parameter Viewer & RF Synthesis Tools
Loading...
Searching...
No Matches
PyModule.cpp
1#ifndef PY_MODULE_CPP
2#define PY_MODULE_CPP
3
4#include "greenlet_internal.hpp"
5
6
7#include "TGreenletGlobals.cpp"
8#include "TMainGreenlet.cpp"
9#include "TThreadStateDestroy.cpp"
10
11using greenlet::LockGuard;
13
14#ifdef __clang__
15# pragma clang diagnostic push
16# pragma clang diagnostic ignored "-Wunused-function"
17# pragma clang diagnostic ignored "-Wunused-variable"
18#endif
19
20PyDoc_STRVAR(mod_getcurrent_doc,
21 "getcurrent() -> greenlet\n"
22 "\n"
23 "Returns the current greenlet (i.e. the one which called this "
24 "function).\n");
25
26static PyObject*
27mod_getcurrent(PyObject* UNUSED(module))
28{
29 return GET_THREAD_STATE().state().get_current().relinquish_ownership_o();
30}
31
32PyDoc_STRVAR(mod_settrace_doc,
33 "settrace(callback) -> object\n"
34 "\n"
35 "Sets a new tracing function and returns the previous one.\n");
36static PyObject*
37mod_settrace(PyObject* UNUSED(module), PyObject* args)
38{
39 PyArgParseParam tracefunc;
40 if (!PyArg_ParseTuple(args, "O", &tracefunc)) {
41 return NULL;
42 }
43 ThreadState& state = GET_THREAD_STATE();
44 OwnedObject previous = state.get_tracefunc();
45 if (!previous) {
46 previous = Py_None;
47 }
48
49 state.set_tracefunc(tracefunc);
50
51 return previous.relinquish_ownership();
52}
53
54PyDoc_STRVAR(mod_gettrace_doc,
55 "gettrace() -> object\n"
56 "\n"
57 "Returns the currently set tracing function, or None.\n");
58
59static PyObject*
60mod_gettrace(PyObject* UNUSED(module))
61{
62 OwnedObject tracefunc = GET_THREAD_STATE().state().get_tracefunc();
63 if (!tracefunc) {
64 tracefunc = Py_None;
65 }
66 return tracefunc.relinquish_ownership();
67}
68
69
70
71PyDoc_STRVAR(mod_set_thread_local_doc,
72 "set_thread_local(key, value) -> None\n"
73 "\n"
74 "Set a value in the current thread-local dictionary. Debugging only.\n");
75
76static PyObject*
77mod_set_thread_local(PyObject* UNUSED(module), PyObject* args)
78{
80 PyArgParseParam value;
81 PyObject* result = NULL;
82
83 if (PyArg_UnpackTuple(args, "set_thread_local", 2, 2, &key, &value)) {
84 if(PyDict_SetItem(
85 PyThreadState_GetDict(), // borrow
86 key,
87 value) == 0 ) {
88 // success
89 Py_INCREF(Py_None);
90 result = Py_None;
91 }
92 }
93 return result;
94}
95
96PyDoc_STRVAR(mod_get_pending_cleanup_count_doc,
97 "get_pending_cleanup_count() -> Integer\n"
98 "\n"
99 "Get the number of greenlet cleanup operations pending. Testing only.\n");
100
101
102static PyObject*
103mod_get_pending_cleanup_count(PyObject* UNUSED(module))
104{
105 LockGuard cleanup_lock(*mod_globs->thread_states_to_destroy_lock);
106 return PyLong_FromSize_t(mod_globs->thread_states_to_destroy.size());
107}
108
109PyDoc_STRVAR(mod_get_total_main_greenlets_doc,
110 "get_total_main_greenlets() -> Integer\n"
111 "\n"
112 "Quickly return the number of main greenlets that exist. Testing only.\n");
113
114static PyObject*
115mod_get_total_main_greenlets(PyObject* UNUSED(module))
116{
117 return PyLong_FromSize_t(G_TOTAL_MAIN_GREENLETS);
118}
119
120
121
122PyDoc_STRVAR(mod_get_clocks_used_doing_optional_cleanup_doc,
123 "get_clocks_used_doing_optional_cleanup() -> Integer\n"
124 "\n"
125 "Get the number of clock ticks the program has used doing optional "
126 "greenlet cleanup.\n"
127 "Beginning in greenlet 2.0, greenlet tries to find and dispose of greenlets\n"
128 "that leaked after a thread exited. This requires invoking Python's garbage collector,\n"
129 "which may have a performance cost proportional to the number of live objects.\n"
130 "This function returns the amount of processor time\n"
131 "greenlet has used to do this. In programs that run with very large amounts of live\n"
132 "objects, this metric can be used to decide whether the cost of doing this cleanup\n"
133 "is worth the memory leak being corrected. If not, you can disable the cleanup\n"
134 "using ``enable_optional_cleanup(False)``.\n"
135 "The units are arbitrary and can only be compared to themselves (similarly to ``time.clock()``);\n"
136 "for example, to see how it scales with your heap. You can attempt to convert them into seconds\n"
137 "by dividing by the value of CLOCKS_PER_SEC."
138 "If cleanup has been disabled, returns None."
139 "\n"
140 "This is an implementation specific, provisional API. It may be changed or removed\n"
141 "in the future.\n"
142 ".. versionadded:: 2.0"
143 );
144static PyObject*
145mod_get_clocks_used_doing_optional_cleanup(PyObject* UNUSED(module))
146{
147 std::clock_t clocks = ThreadState::clocks_used_doing_gc();
148
149 if (clocks == std::clock_t(-1)) {
150 Py_RETURN_NONE;
151 }
152 // This might not actually work on some implementations; clock_t
153 // is an opaque type.
154 return PyLong_FromSsize_t(clocks);
155}
156
157PyDoc_STRVAR(mod_enable_optional_cleanup_doc,
158 "mod_enable_optional_cleanup(bool) -> None\n"
159 "\n"
160 "Enable or disable optional cleanup operations.\n"
161 "See ``get_clocks_used_doing_optional_cleanup()`` for details.\n"
162 );
163static PyObject*
164mod_enable_optional_cleanup(PyObject* UNUSED(module), PyObject* flag)
165{
166 int is_true = PyObject_IsTrue(flag);
167 if (is_true == -1) {
168 return nullptr;
169 }
170
171 if (is_true) {
172 std::clock_t clocks = ThreadState::clocks_used_doing_gc();
173 // If we already have a value, we don't want to lose it.
174 if (clocks == std::clock_t(-1)) {
175 ThreadState::set_clocks_used_doing_gc(0);
176 }
177 }
178 else {
179 ThreadState::set_clocks_used_doing_gc(std::clock_t(-1));
180 }
181 Py_RETURN_NONE;
182}
183
184
185
186
187#if !GREENLET_PY313
188PyDoc_STRVAR(mod_get_tstate_trash_delete_nesting_doc,
189 "get_tstate_trash_delete_nesting() -> Integer\n"
190 "\n"
191 "Return the 'trash can' nesting level. Testing only.\n");
192static PyObject*
193mod_get_tstate_trash_delete_nesting(PyObject* UNUSED(module))
194{
195 PyThreadState* tstate = PyThreadState_GET();
196
197#if GREENLET_PY312
198 return PyLong_FromLong(tstate->trash.delete_nesting);
199#else
200 return PyLong_FromLong(tstate->trash_delete_nesting);
201#endif
202}
203#endif
204
205
206
207
208static PyMethodDef GreenMethods[] = {
209 {
210 .ml_name="getcurrent",
211 .ml_meth=(PyCFunction)mod_getcurrent,
212 .ml_flags=METH_NOARGS,
213 .ml_doc=mod_getcurrent_doc
214 },
215 {
216 .ml_name="settrace",
217 .ml_meth=(PyCFunction)mod_settrace,
218 .ml_flags=METH_VARARGS,
219 .ml_doc=mod_settrace_doc
220 },
221 {
222 .ml_name="gettrace",
223 .ml_meth=(PyCFunction)mod_gettrace,
224 .ml_flags=METH_NOARGS,
225 .ml_doc=mod_gettrace_doc
226 },
227 {
228 .ml_name="set_thread_local",
229 .ml_meth=(PyCFunction)mod_set_thread_local,
230 .ml_flags=METH_VARARGS,
231 .ml_doc=mod_set_thread_local_doc
232 },
233 {
234 .ml_name="get_pending_cleanup_count",
235 .ml_meth=(PyCFunction)mod_get_pending_cleanup_count,
236 .ml_flags=METH_NOARGS,
237 .ml_doc=mod_get_pending_cleanup_count_doc
238 },
239 {
240 .ml_name="get_total_main_greenlets",
241 .ml_meth=(PyCFunction)mod_get_total_main_greenlets,
242 .ml_flags=METH_NOARGS,
243 .ml_doc=mod_get_total_main_greenlets_doc
244 },
245 {
246 .ml_name="get_clocks_used_doing_optional_cleanup",
247 .ml_meth=(PyCFunction)mod_get_clocks_used_doing_optional_cleanup,
248 .ml_flags=METH_NOARGS,
249 .ml_doc=mod_get_clocks_used_doing_optional_cleanup_doc
250 },
251 {
252 .ml_name="enable_optional_cleanup",
253 .ml_meth=(PyCFunction)mod_enable_optional_cleanup,
254 .ml_flags=METH_O,
255 .ml_doc=mod_enable_optional_cleanup_doc
256 },
257#if !GREENLET_PY313
258 {
259 .ml_name="get_tstate_trash_delete_nesting",
260 .ml_meth=(PyCFunction)mod_get_tstate_trash_delete_nesting,
261 .ml_flags=METH_NOARGS,
262 .ml_doc=mod_get_tstate_trash_delete_nesting_doc
263 },
264#endif
265 {.ml_name=NULL, .ml_meth=NULL} /* Sentinel */
266};
267
268static const char* const copy_on_greentype[] = {
269 "getcurrent",
270 "error",
271 "GreenletExit",
272 "settrace",
273 "gettrace",
274 NULL
275};
276
277static struct PyModuleDef greenlet_module_def = {
278 .m_base=PyModuleDef_HEAD_INIT,
279 .m_name="greenlet._greenlet",
280 .m_doc=NULL,
281 .m_size=-1,
282 .m_methods=GreenMethods,
283};
284
285
286#endif
287
288#ifdef __clang__
289# pragma clang diagnostic pop
290#elif defined(__GNUC__)
291# pragma GCC diagnostic pop
292#endif
Definition TThreadState.hpp:87
static std::clock_t clocks_used_doing_gc()
Definition TThreadState.hpp:352
Definition greenlet_refs.hpp:1102