1*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/Device.h>
2*da0073e9SAndroid Build Coastguard Worker
3*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/Exceptions.h>
4*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/object_ptr.h>
5*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/pybind.h>
6*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/python_arg_parser.h>
7*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/python_numbers.h>
8*da0073e9SAndroid Build Coastguard Worker #include <torch/csrc/utils/python_strings.h>
9*da0073e9SAndroid Build Coastguard Worker
10*da0073e9SAndroid Build Coastguard Worker #include <ATen/Device.h>
11*da0073e9SAndroid Build Coastguard Worker #include <c10/util/Exception.h>
12*da0073e9SAndroid Build Coastguard Worker
13*da0073e9SAndroid Build Coastguard Worker #include <structmember.h>
14*da0073e9SAndroid Build Coastguard Worker #include <limits>
15*da0073e9SAndroid Build Coastguard Worker #include <sstream>
16*da0073e9SAndroid Build Coastguard Worker
17*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
18*da0073e9SAndroid Build Coastguard Worker PyObject* THPUpperModuleOfDevice = nullptr;
19*da0073e9SAndroid Build Coastguard Worker
THPDevice_New(const at::Device & device)20*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_New(const at::Device& device) {
21*da0073e9SAndroid Build Coastguard Worker auto type = (PyTypeObject*)&THPDeviceType;
22*da0073e9SAndroid Build Coastguard Worker auto self = THPObjectPtr{type->tp_alloc(type, 0)};
23*da0073e9SAndroid Build Coastguard Worker if (!self)
24*da0073e9SAndroid Build Coastguard Worker throw python_error();
25*da0073e9SAndroid Build Coastguard Worker auto self_ = reinterpret_cast<THPDevice*>(self.get());
26*da0073e9SAndroid Build Coastguard Worker self_->device = device;
27*da0073e9SAndroid Build Coastguard Worker return self.release();
28*da0073e9SAndroid Build Coastguard Worker }
29*da0073e9SAndroid Build Coastguard Worker
THPDevice_repr(THPDevice * self)30*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_repr(THPDevice* self) {
31*da0073e9SAndroid Build Coastguard Worker std::ostringstream oss;
32*da0073e9SAndroid Build Coastguard Worker oss << "device(type=\'" << self->device.type() << "\'";
33*da0073e9SAndroid Build Coastguard Worker if (self->device.has_index()) {
34*da0073e9SAndroid Build Coastguard Worker // `self->device.index()` returns uint8_t which is treated as ascii while
35*da0073e9SAndroid Build Coastguard Worker // printing, hence casting it to uint16_t.
36*da0073e9SAndroid Build Coastguard Worker // https://stackoverflow.com/questions/19562103/uint8-t-cant-be-printed-with-cout
37*da0073e9SAndroid Build Coastguard Worker oss << ", index=" << static_cast<uint16_t>(self->device.index());
38*da0073e9SAndroid Build Coastguard Worker }
39*da0073e9SAndroid Build Coastguard Worker oss << ")";
40*da0073e9SAndroid Build Coastguard Worker return THPUtils_packString(oss.str().c_str());
41*da0073e9SAndroid Build Coastguard Worker }
42*da0073e9SAndroid Build Coastguard Worker
THPDevice_str(THPDevice * self)43*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_str(THPDevice* self) {
44*da0073e9SAndroid Build Coastguard Worker std::ostringstream oss;
45*da0073e9SAndroid Build Coastguard Worker oss << self->device;
46*da0073e9SAndroid Build Coastguard Worker return THPUtils_packString(oss.str().c_str());
47*da0073e9SAndroid Build Coastguard Worker }
48*da0073e9SAndroid Build Coastguard Worker
THPDevice_pynew(PyTypeObject * type,PyObject * args,PyObject * kwargs)49*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_pynew(
50*da0073e9SAndroid Build Coastguard Worker PyTypeObject* type,
51*da0073e9SAndroid Build Coastguard Worker PyObject* args,
52*da0073e9SAndroid Build Coastguard Worker PyObject* kwargs) {
53*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
54*da0073e9SAndroid Build Coastguard Worker static torch::PythonArgParser parser(
55*da0073e9SAndroid Build Coastguard Worker {"device(Device device)",
56*da0073e9SAndroid Build Coastguard Worker "device(c10::string_view type, int64_t? index=-1)"});
57*da0073e9SAndroid Build Coastguard Worker torch::ParsedArgs<2> parsed_args;
58*da0073e9SAndroid Build Coastguard Worker auto r = parser.parse(args, kwargs, parsed_args);
59*da0073e9SAndroid Build Coastguard Worker if (r.has_torch_function()) {
60*da0073e9SAndroid Build Coastguard Worker return handle_torch_function(
61*da0073e9SAndroid Build Coastguard Worker r, nullptr, args, kwargs, THPUpperModuleOfDevice, "torch");
62*da0073e9SAndroid Build Coastguard Worker }
63*da0073e9SAndroid Build Coastguard Worker if (r.idx == 0) {
64*da0073e9SAndroid Build Coastguard Worker auto device = r.device(0);
65*da0073e9SAndroid Build Coastguard Worker return THPDevice_New(device);
66*da0073e9SAndroid Build Coastguard Worker } else if (r.idx == 1) {
67*da0073e9SAndroid Build Coastguard Worker auto as_device = r.device(0); // this works, because device can take strings
68*da0073e9SAndroid Build Coastguard Worker if (as_device.has_index()) {
69*da0073e9SAndroid Build Coastguard Worker auto device_type = r.string(0);
70*da0073e9SAndroid Build Coastguard Worker throw std::runtime_error(
71*da0073e9SAndroid Build Coastguard Worker "type (string) must not include an index because index "
72*da0073e9SAndroid Build Coastguard Worker "was passed explicitly: " +
73*da0073e9SAndroid Build Coastguard Worker device_type);
74*da0073e9SAndroid Build Coastguard Worker }
75*da0073e9SAndroid Build Coastguard Worker int64_t device_index = -1;
76*da0073e9SAndroid Build Coastguard Worker if (!r.isNone(1)) {
77*da0073e9SAndroid Build Coastguard Worker device_index = r.toInt64(1);
78*da0073e9SAndroid Build Coastguard Worker // -1 is allowed in ATen/C++, to mean the default device, but not in
79*da0073e9SAndroid Build Coastguard Worker // Python.
80*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK(device_index >= 0, "Device index must not be negative");
81*da0073e9SAndroid Build Coastguard Worker }
82*da0073e9SAndroid Build Coastguard Worker at::Device device(
83*da0073e9SAndroid Build Coastguard Worker as_device.type(), static_cast<c10::DeviceIndex>(device_index));
84*da0073e9SAndroid Build Coastguard Worker return THPDevice_New(device);
85*da0073e9SAndroid Build Coastguard Worker }
86*da0073e9SAndroid Build Coastguard Worker Py_RETURN_NONE;
87*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
88*da0073e9SAndroid Build Coastguard Worker }
89*da0073e9SAndroid Build Coastguard Worker
THPDevice_type(THPDevice * self,PyObject * noargs)90*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_type(THPDevice* self, PyObject* noargs) {
91*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
92*da0073e9SAndroid Build Coastguard Worker std::ostringstream oss;
93*da0073e9SAndroid Build Coastguard Worker oss << self->device.type();
94*da0073e9SAndroid Build Coastguard Worker return THPUtils_packString(oss.str().c_str());
95*da0073e9SAndroid Build Coastguard Worker Py_RETURN_NONE;
96*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
97*da0073e9SAndroid Build Coastguard Worker }
98*da0073e9SAndroid Build Coastguard Worker
THPDevice_index(THPDevice * self,PyObject * noargs)99*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_index(THPDevice* self, PyObject* noargs) {
100*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
101*da0073e9SAndroid Build Coastguard Worker if (self->device.has_index()) {
102*da0073e9SAndroid Build Coastguard Worker return THPUtils_packInt64(self->device.index());
103*da0073e9SAndroid Build Coastguard Worker } else {
104*da0073e9SAndroid Build Coastguard Worker Py_RETURN_NONE;
105*da0073e9SAndroid Build Coastguard Worker }
106*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
107*da0073e9SAndroid Build Coastguard Worker }
108*da0073e9SAndroid Build Coastguard Worker
THPDevice_hash(THPDevice * self)109*da0073e9SAndroid Build Coastguard Worker static Py_ssize_t THPDevice_hash(THPDevice* self) {
110*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
111*da0073e9SAndroid Build Coastguard Worker return static_cast<Py_ssize_t>(
112*da0073e9SAndroid Build Coastguard Worker std::hash<at::Device>{}(self->device) %
113*da0073e9SAndroid Build Coastguard Worker std::numeric_limits<Py_ssize_t>::max());
114*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS_RET(-1)
115*da0073e9SAndroid Build Coastguard Worker }
116*da0073e9SAndroid Build Coastguard Worker
THPDevice_rc(PyObject * a,PyObject * b,int op)117*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_rc(PyObject* a, PyObject* b, int op) {
118*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
119*da0073e9SAndroid Build Coastguard Worker if (!THPDevice_Check(a) || !THPDevice_Check(b)) {
120*da0073e9SAndroid Build Coastguard Worker // Py_RETURN_NOTIMPLEMENTED not in python 2.
121*da0073e9SAndroid Build Coastguard Worker Py_INCREF(Py_NotImplemented);
122*da0073e9SAndroid Build Coastguard Worker return Py_NotImplemented;
123*da0073e9SAndroid Build Coastguard Worker }
124*da0073e9SAndroid Build Coastguard Worker THPDevice* da = reinterpret_cast<THPDevice*>(a);
125*da0073e9SAndroid Build Coastguard Worker THPDevice* db = reinterpret_cast<THPDevice*>(b);
126*da0073e9SAndroid Build Coastguard Worker
127*da0073e9SAndroid Build Coastguard Worker switch (op) {
128*da0073e9SAndroid Build Coastguard Worker case Py_EQ:
129*da0073e9SAndroid Build Coastguard Worker if (da->device == db->device) {
130*da0073e9SAndroid Build Coastguard Worker Py_RETURN_TRUE;
131*da0073e9SAndroid Build Coastguard Worker } else {
132*da0073e9SAndroid Build Coastguard Worker Py_RETURN_FALSE;
133*da0073e9SAndroid Build Coastguard Worker }
134*da0073e9SAndroid Build Coastguard Worker case Py_NE:
135*da0073e9SAndroid Build Coastguard Worker if (da->device == db->device) {
136*da0073e9SAndroid Build Coastguard Worker Py_RETURN_FALSE;
137*da0073e9SAndroid Build Coastguard Worker } else {
138*da0073e9SAndroid Build Coastguard Worker Py_RETURN_TRUE;
139*da0073e9SAndroid Build Coastguard Worker }
140*da0073e9SAndroid Build Coastguard Worker case Py_LT:
141*da0073e9SAndroid Build Coastguard Worker case Py_LE:
142*da0073e9SAndroid Build Coastguard Worker case Py_GT:
143*da0073e9SAndroid Build Coastguard Worker case Py_GE:
144*da0073e9SAndroid Build Coastguard Worker throw torch::TypeError("comparison not implemented");
145*da0073e9SAndroid Build Coastguard Worker default:
146*da0073e9SAndroid Build Coastguard Worker throw torch::TypeError("unexpected comparison op");
147*da0073e9SAndroid Build Coastguard Worker }
148*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
149*da0073e9SAndroid Build Coastguard Worker }
150*da0073e9SAndroid Build Coastguard Worker
THPDevice_reduce(PyObject * _self,PyObject * noargs)151*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_reduce(PyObject* _self, PyObject* noargs) {
152*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
153*da0073e9SAndroid Build Coastguard Worker auto self = (THPDevice*)_self;
154*da0073e9SAndroid Build Coastguard Worker auto ret = THPObjectPtr{PyTuple_New(2)};
155*da0073e9SAndroid Build Coastguard Worker if (!ret)
156*da0073e9SAndroid Build Coastguard Worker throw python_error();
157*da0073e9SAndroid Build Coastguard Worker
158*da0073e9SAndroid Build Coastguard Worker py::object torch_module = py::module::import("torch");
159*da0073e9SAndroid Build Coastguard Worker py::object torch_device = torch_module.attr("device");
160*da0073e9SAndroid Build Coastguard Worker PyTuple_SET_ITEM(ret.get(), 0, torch_device.release().ptr());
161*da0073e9SAndroid Build Coastguard Worker
162*da0073e9SAndroid Build Coastguard Worker THPObjectPtr args;
163*da0073e9SAndroid Build Coastguard Worker std::ostringstream oss;
164*da0073e9SAndroid Build Coastguard Worker oss << self->device.type();
165*da0073e9SAndroid Build Coastguard Worker if (self->device.has_index()) {
166*da0073e9SAndroid Build Coastguard Worker args = THPObjectPtr{Py_BuildValue(
167*da0073e9SAndroid Build Coastguard Worker "(si)", oss.str().c_str(), static_cast<int>(self->device.index()))};
168*da0073e9SAndroid Build Coastguard Worker } else {
169*da0073e9SAndroid Build Coastguard Worker args = THPObjectPtr{Py_BuildValue("(s)", oss.str().c_str())};
170*da0073e9SAndroid Build Coastguard Worker }
171*da0073e9SAndroid Build Coastguard Worker if (!args)
172*da0073e9SAndroid Build Coastguard Worker throw python_error();
173*da0073e9SAndroid Build Coastguard Worker PyTuple_SET_ITEM(ret.get(), 1, args.release());
174*da0073e9SAndroid Build Coastguard Worker
175*da0073e9SAndroid Build Coastguard Worker return ret.release();
176*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
177*da0073e9SAndroid Build Coastguard Worker }
178*da0073e9SAndroid Build Coastguard Worker
THPDevice_enter(PyObject * self,PyObject * noargs)179*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_enter(PyObject* self, PyObject* noargs) {
180*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
181*da0073e9SAndroid Build Coastguard Worker py::object mode = py::module::import("torch.utils._device")
182*da0073e9SAndroid Build Coastguard Worker .attr("DeviceContext")(py::handle(self));
183*da0073e9SAndroid Build Coastguard Worker at::impl::PythonTorchFunctionTLS::push_onto_stack(
184*da0073e9SAndroid Build Coastguard Worker std::make_shared<c10::SafePyObject>(
185*da0073e9SAndroid Build Coastguard Worker mode.release().ptr(), getPyInterpreter()));
186*da0073e9SAndroid Build Coastguard Worker // So that with torch.device('cuda') as dev: works
187*da0073e9SAndroid Build Coastguard Worker Py_INCREF(self);
188*da0073e9SAndroid Build Coastguard Worker return self;
189*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
190*da0073e9SAndroid Build Coastguard Worker }
191*da0073e9SAndroid Build Coastguard Worker
THPDevice_exit(PyObject * self,PyObject * unused)192*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_exit(PyObject* self, PyObject* unused) {
193*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
194*da0073e9SAndroid Build Coastguard Worker at::impl::PythonTorchFunctionTLS::pop_stack();
195*da0073e9SAndroid Build Coastguard Worker Py_RETURN_NONE;
196*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
197*da0073e9SAndroid Build Coastguard Worker }
198*da0073e9SAndroid Build Coastguard Worker
THPDevice_call(PyObject * self,PyObject * args,PyObject * kwargs)199*da0073e9SAndroid Build Coastguard Worker PyObject* THPDevice_call(PyObject* self, PyObject* args, PyObject* kwargs) {
200*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS
201*da0073e9SAndroid Build Coastguard Worker py::object deco =
202*da0073e9SAndroid Build Coastguard Worker py::module::import("torch.utils._device").attr("device_decorator");
203*da0073e9SAndroid Build Coastguard Worker return deco(py::handle(self), *py::handle(args), **py::handle(kwargs))
204*da0073e9SAndroid Build Coastguard Worker .release()
205*da0073e9SAndroid Build Coastguard Worker .ptr();
206*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS
207*da0073e9SAndroid Build Coastguard Worker }
208*da0073e9SAndroid Build Coastguard Worker
209*da0073e9SAndroid Build Coastguard Worker typedef PyObject* (*getter)(PyObject*, void*);
210*da0073e9SAndroid Build Coastguard Worker
211*da0073e9SAndroid Build Coastguard Worker // NB: If you edit these properties/methods, update torch/_C/__init__.pyi.in
212*da0073e9SAndroid Build Coastguard Worker
213*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,cppcoreguidelines-avoid-non-const-global-variables,modernize-avoid-c-arrays)
214*da0073e9SAndroid Build Coastguard Worker static struct PyGetSetDef THPDevice_properties[] = {
215*da0073e9SAndroid Build Coastguard Worker {"type", (getter)THPDevice_type, nullptr, nullptr, nullptr},
216*da0073e9SAndroid Build Coastguard Worker {"index", (getter)THPDevice_index, nullptr, nullptr, nullptr},
217*da0073e9SAndroid Build Coastguard Worker {nullptr}};
218*da0073e9SAndroid Build Coastguard Worker
219*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,cppcoreguidelines-avoid-non-const-global-variables,modernize-avoid-c-arrays)
220*da0073e9SAndroid Build Coastguard Worker static PyMethodDef THPDevice_methods[] = {
221*da0073e9SAndroid Build Coastguard Worker {"__reduce__", THPDevice_reduce, METH_NOARGS, nullptr},
222*da0073e9SAndroid Build Coastguard Worker {"__enter__", THPDevice_enter, METH_NOARGS, nullptr},
223*da0073e9SAndroid Build Coastguard Worker {"__exit__", THPDevice_exit, METH_VARARGS, nullptr},
224*da0073e9SAndroid Build Coastguard Worker {nullptr} /* Sentinel */
225*da0073e9SAndroid Build Coastguard Worker };
226*da0073e9SAndroid Build Coastguard Worker
227*da0073e9SAndroid Build Coastguard Worker PyTypeObject THPDeviceType = {
228*da0073e9SAndroid Build Coastguard Worker PyVarObject_HEAD_INIT(nullptr, 0) "torch.device", /* tp_name */
229*da0073e9SAndroid Build Coastguard Worker sizeof(THPDevice), /* tp_basicsize */
230*da0073e9SAndroid Build Coastguard Worker 0, /* tp_itemsize */
231*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_dealloc */
232*da0073e9SAndroid Build Coastguard Worker 0, /* tp_vectorcall_offset */
233*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_getattr */
234*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_setattr */
235*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_reserved */
236*da0073e9SAndroid Build Coastguard Worker (reprfunc)THPDevice_repr, /* tp_repr */
237*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_as_number */
238*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_as_sequence */
239*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_as_mapping */
240*da0073e9SAndroid Build Coastguard Worker (hashfunc)THPDevice_hash, /* tp_hash */
241*da0073e9SAndroid Build Coastguard Worker // TODO: We're not sure if this is a good idea or not, because making
242*da0073e9SAndroid Build Coastguard Worker // torch.device callable means that it will start returning true
243*da0073e9SAndroid Build Coastguard Worker // for callable() queries, and that is unexpected. We can always add
244*da0073e9SAndroid Build Coastguard Worker // this later, so for now, don't actually implement this
245*da0073e9SAndroid Build Coastguard Worker // THPDevice_call, /* tp_call */
246*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_call */
247*da0073e9SAndroid Build Coastguard Worker (reprfunc)THPDevice_str, /* tp_str */
248*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_getattro */
249*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_setattro */
250*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_as_buffer */
251*da0073e9SAndroid Build Coastguard Worker Py_TPFLAGS_DEFAULT, /* tp_flags */
252*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_doc */
253*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_traverse */
254*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_clear */
255*da0073e9SAndroid Build Coastguard Worker (richcmpfunc)THPDevice_rc, /* tp_richcompare */
256*da0073e9SAndroid Build Coastguard Worker 0, /* tp_weaklistoffset */
257*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_iter */
258*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_iternext */
259*da0073e9SAndroid Build Coastguard Worker THPDevice_methods, /* tp_methods */
260*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_members */
261*da0073e9SAndroid Build Coastguard Worker THPDevice_properties, /* tp_getset */
262*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_base */
263*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_dict */
264*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_descr_get */
265*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_descr_set */
266*da0073e9SAndroid Build Coastguard Worker 0, /* tp_dictoffset */
267*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_init */
268*da0073e9SAndroid Build Coastguard Worker nullptr, /* tp_alloc */
269*da0073e9SAndroid Build Coastguard Worker THPDevice_pynew, /* tp_new */
270*da0073e9SAndroid Build Coastguard Worker };
271*da0073e9SAndroid Build Coastguard Worker
THPDevice_init(PyObject * module)272*da0073e9SAndroid Build Coastguard Worker void THPDevice_init(PyObject* module) {
273*da0073e9SAndroid Build Coastguard Worker if (PyType_Ready(&THPDeviceType) < 0) {
274*da0073e9SAndroid Build Coastguard Worker throw python_error();
275*da0073e9SAndroid Build Coastguard Worker }
276*da0073e9SAndroid Build Coastguard Worker Py_INCREF(&THPDeviceType);
277*da0073e9SAndroid Build Coastguard Worker THPUpperModuleOfDevice = module;
278*da0073e9SAndroid Build Coastguard Worker if (PyModule_AddObject(module, "device", (PyObject*)&THPDeviceType) != 0) {
279*da0073e9SAndroid Build Coastguard Worker throw python_error();
280*da0073e9SAndroid Build Coastguard Worker }
281*da0073e9SAndroid Build Coastguard Worker }
282