| #pragma once |
| |
| #include <c10/core/impl/PyInterpreter.h> |
| #include <c10/macros/Macros.h> |
| #include <c10/util/python_stub.h> |
| |
| namespace c10 { |
| |
| // This is an safe owning holder for a PyObject, akin to pybind11's |
| // py::object, with two major differences: |
| // |
| // - It is in c10/core; i.e., you can use this type in contexts where |
| // you do not have a libpython dependency |
| // |
| // - It is multi-interpreter safe (ala torchdeploy); when you fetch |
| // the underlying PyObject* you are required to specify what the current |
| // interpreter context is and we will check that you match it. |
| // |
| // It is INVALID to store a reference to a Tensor object in this way; |
| // you should just use TensorImpl directly in that case! |
| struct C10_API SafePyObject { |
| // Steals a reference to data |
| SafePyObject(PyObject* data, c10::impl::PyInterpreter* pyinterpreter) |
| : data_(data), pyinterpreter_(pyinterpreter) {} |
| |
| // In principle this could be copyable if we add an incref to PyInterpreter |
| // but for now it's easier to just disallow it. |
| SafePyObject(SafePyObject const&) = delete; |
| SafePyObject& operator=(SafePyObject const&) = delete; |
| |
| ~SafePyObject() { |
| (*pyinterpreter_)->decref(data_, /*is_tensor*/ false); |
| } |
| |
| c10::impl::PyInterpreter& pyinterpreter() const { |
| return *pyinterpreter_; |
| } |
| PyObject* ptr(const c10::impl::PyInterpreter*) const; |
| |
| private: |
| PyObject* data_; |
| c10::impl::PyInterpreter* pyinterpreter_; |
| }; |
| |
| // Like SafePyObject, but non-owning. Good for references to global PyObjects |
| // that will be leaked on interpreter exit. You get a copy constructor/assign |
| // this way. |
| struct C10_API SafePyHandle { |
| SafePyHandle() : data_(nullptr), pyinterpreter_(nullptr) {} |
| SafePyHandle(PyObject* data, c10::impl::PyInterpreter* pyinterpreter) |
| : data_(data), pyinterpreter_(pyinterpreter) {} |
| |
| c10::impl::PyInterpreter& pyinterpreter() const { |
| return *pyinterpreter_; |
| } |
| PyObject* ptr(const c10::impl::PyInterpreter*) const; |
| void reset() { |
| data_ = nullptr; |
| pyinterpreter_ = nullptr; |
| } |
| operator bool() { |
| return data_; |
| } |
| |
| private: |
| PyObject* data_; |
| c10::impl::PyInterpreter* pyinterpreter_; |
| }; |
| |
| } // namespace c10 |