1#pragma once
2
3#include <torch/csrc/python_headers.h>
4
5template <class T>
6class THPPointer {
7 public:
8 THPPointer() : ptr(nullptr){};
9 explicit THPPointer(T* ptr) noexcept : ptr(ptr){};
10 THPPointer(THPPointer&& p) noexcept {
11 free();
12 ptr = p.ptr;
13 p.ptr = nullptr;
14 };
15
16 ~THPPointer() {
17 free();
18 };
19 T* get() {
20 return ptr;
21 }
22 const T* get() const {
23 return ptr;
24 }
25 T* release() {
26 T* tmp = ptr;
27 ptr = nullptr;
28 return tmp;
29 }
30 operator T*() {
31 return ptr;
32 }
33 THPPointer& operator=(T* new_ptr) noexcept {
34 free();
35 ptr = new_ptr;
36 return *this;
37 }
38 THPPointer& operator=(THPPointer&& p) noexcept {
39 free();
40 ptr = p.ptr;
41 p.ptr = nullptr;
42 return *this;
43 }
44 T* operator->() {
45 return ptr;
46 }
47 explicit operator bool() const {
48 return ptr != nullptr;
49 }
50
51 private:
52 void free();
53 T* ptr = nullptr;
54};
55
56/**
57 * An RAII-style, owning pointer to a PyObject. You must protect
58 * destruction of this object with the GIL.
59 *
60 * WARNING: Think twice before putting this as a field in a C++
61 * struct. This class does NOT take out the GIL on destruction,
62 * so if you will need to ensure that the destructor of your struct
63 * is either (a) always invoked when the GIL is taken or (b) takes
64 * out the GIL itself. Easiest way to avoid this problem is to
65 * not use THPPointer in this situation.
66 */
67using THPObjectPtr = THPPointer<PyObject>;
68using THPCodeObjectPtr = THPPointer<PyCodeObject>;
69using THPFrameObjectPtr = THPPointer<PyFrameObject>;
70