codekingpro/portable-devtools
115k
1#ifndef COBJECTS_CPP
2#define COBJECTS_CPP
3/*****************************************************************************
4 * C interface
5 *
6 * These are exported using the CObject API
7 */
8#ifdef __clang__
9# pragma clang diagnostic push
10# pragma clang diagnostic ignored "-Wunused-function"
11#endif
12
13#include "greenlet_exceptions.hpp"
14
15#include "greenlet_internal.hpp"
16#include "greenlet_refs.hpp"
17
18
19#include "TThreadStateDestroy.cpp"
20
21#include "PyGreenlet.hpp"
22
23using greenlet::PyErrOccurred;
24using greenlet::Require;
25
26
27
28extern "C" {
29static PyGreenlet*
30PyGreenlet_GetCurrent(void)
31{
32 if (greenlet::IsShuttingDown()) {
33 PyErr_SetString(PyExc_RuntimeError, "greenlet is being finalized");
34 return nullptr;
35 }
36 return GET_THREAD_STATE().state().get_current().relinquish_ownership();
37}
38
39static int
40PyGreenlet_SetParent(PyGreenlet* g, PyGreenlet* nparent)
41{
42 return green_setparent((PyGreenlet*)g, (PyObject*)nparent, NULL);
43}
44
45static PyGreenlet*
46PyGreenlet_New(PyObject* run, PyGreenlet* parent)
47{
48 using greenlet::refs::NewDictReference;
49 // In the past, we didn't use green_new and green_init, but that
50 // was a maintenance issue because we duplicated code. This way is
51 // much safer, but slightly slower. If that's a problem, we could
52 // refactor green_init to separate argument parsing from initialization.
53 OwnedGreenlet g = OwnedGreenlet::consuming(green_new(&PyGreenlet_Type, nullptr, nullptr));
54 if (!g) {
55 return NULL;
56 }
57
58 try {
59 NewDictReference kwargs;
60 if (run) {
61 kwargs.SetItem(mod_globs->str_run, run);
62 }
63 if (parent) {
64 kwargs.SetItem("parent", (PyObject*)parent);
65 }
66
67 Require(green_init(g.borrow(), mod_globs->empty_tuple, kwargs.borrow()));
68 }
69 catch (const PyErrOccurred&) {
70 return nullptr;
71 }
72
73 return g.relinquish_ownership();
74}
75
76static PyObject*
77PyGreenlet_Switch(PyGreenlet* self, PyObject* args, PyObject* kwargs)
78{
79 if (!PyGreenlet_Check(self)) {
80 PyErr_BadArgument();
81 return NULL;
82 }
83
84 if (args == NULL) {
85 args = mod_globs->empty_tuple;
86 }
87
88 if (kwargs == NULL || !PyDict_Check(kwargs)) {
89 kwargs = NULL;
90 }
91
92 return green_switch(self, args, kwargs);
93}
94
95static PyObject*
96PyGreenlet_Throw(PyGreenlet* self, PyObject* typ, PyObject* val, PyObject* tb)
97{
98 if (!PyGreenlet_Check(self)) {
99 PyErr_BadArgument();
100 return nullptr;
101 }
102 try {
103 PyErrPieces err_pieces(typ, val, tb);
104 return internal_green_throw(self, err_pieces).relinquish_ownership();
105 }
106 catch (const PyErrOccurred&) {
107 return nullptr;
108 }
109}
110
111
112
113static int
114Extern_PyGreenlet_MAIN(PyGreenlet* self)
115{
116 if (!PyGreenlet_Check(self)) {
117 PyErr_BadArgument();
118 return -1;
119 }
120 return self->pimpl->main();
121}
122
123static int
124Extern_PyGreenlet_ACTIVE(PyGreenlet* self)
125{
126 if (!PyGreenlet_Check(self)) {
127 PyErr_BadArgument();
128 return -1;
129 }
130 return self->pimpl->active();
131}
132
133static int
134Extern_PyGreenlet_STARTED(PyGreenlet* self)
135{
136 if (!PyGreenlet_Check(self)) {
137 PyErr_BadArgument();
138 return -1;
139 }
140 return self->pimpl->started();
141}
142
143static PyGreenlet*
144Extern_PyGreenlet_GET_PARENT(PyGreenlet* self)
145{
146 if (!PyGreenlet_Check(self)) {
147 PyErr_BadArgument();
148 return NULL;
149 }
150 // This can return NULL even if there is no exception
151 return self->pimpl->parent().acquire();
152}
153} // extern C.
154
155/** End C API ****************************************************************/
156#ifdef __clang__
157# pragma clang diagnostic pop
158#endif
159
160
161#endif
162 