HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pyIdentity.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_TF_PY_IDENTITY_H
25 #define PXR_BASE_TF_PY_IDENTITY_H
26 
27 #include "pxr/pxr.h"
28 
29 #include "pxr/base/tf/api.h"
30 #include "pxr/base/tf/pyLock.h"
31 #include "pxr/base/tf/pyUtils.h"
32 
33 #include "pxr/base/arch/demangle.h"
34 #include "pxr/base/tf/diagnostic.h"
35 #include "pxr/base/tf/refPtr.h"
38 #include "pxr/base/tf/weakPtr.h"
39 
40 #include <hboost/python/class.hpp>
41 #include <hboost/python/handle.hpp>
42 #include <hboost/python/object.hpp>
43 #include <hboost/type_traits/is_base_of.hpp>
44 #include <hboost/utility.hpp>
45 
46 #include "pxr/base/tf/hashmap.h"
47 
48 // Specializations for hboost::python::pointee and get_pointer for TfRefPtr and
49 // TfWeakPtr.
50 namespace hboost { namespace python {
51 
52 // TfWeakPtrFacade
53 template <template <class> class X, class Y>
54 struct pointee< PXR_NS::TfWeakPtrFacade<X, Y> > {
55  typedef Y type;
56 };
57 
58 // TfRefPtr
59 template <typename T>
60 struct pointee< PXR_NS::TfRefPtr<T> > {
61  typedef T type;
62 };
63 
64 }}
65 
67 
69 {
70  // Set the identity of ptr (which derives from TfPtrBase) to be the
71  // python object \a obj.
72  TF_API
73  static void Set(void const *id, PyObject *obj);
74 
75  // Return a new reference to the python object associated with ptr. If
76  // there is none, return 0.
77  TF_API
78  static PyObject *Get(void const *id);
79 
80  TF_API
81  static void Erase(void const *id);
82 
83  // Acquire a reference to the python object associated with ptrBase
84  // if not already acquired.
85  TF_API
86  static void Acquire(void const *id);
87 
88  // Release a reference to the python object associated with ptrBase
89  // if we own a reference.
90  TF_API
91  static void Release(void const *id);
92 
93 };
94 
95 template <class Ptr>
96 void Tf_PyReleasePythonIdentity(Ptr const &ptr, PyObject *obj)
97 {
98  Tf_PySetPythonIdentity(ptr, obj);
99  Tf_PyIdentityHelper::Release(ptr.GetUniqueIdentifier());
100 }
101 
103  bool isNowUnique);
104 
106 {
109  TF_API
110  static void Insert(TfRefBase *refBase, void const *uniqueId);
111  TF_API
112  static void const *Lookup(TfRefBase const *refBase);
113  TF_API
114  static void Erase(TfRefBase *refBase);
115  private:
116  static _CacheType _cache;
117 };
118 
119 
120 // Doxygen generates files whose names are mangled typenames. This is fine
121 // except when the filenames get longer than 256 characters. This is one case
122 // of that, so we'll just disable doxygen. There's no actual doxygen doc here,
123 // so this is fine. If/when this gets solved for real, we can remove this
124 // (6/06)
125 #ifndef doxygen
126 
127 
128 template <class Ptr, typename Enable = void>
130  template <typename U>
131  static void Add(U const &, const void *, PyObject *) {}
132  template <typename U>
133  static void Remove(U const &, PyObject *) {}
134 };
135 
136 template <typename Ptr>
138  typename hboost::enable_if<
139  hboost::mpl::and_<hboost::is_same<TfRefPtr<typename Ptr::DataType>, Ptr>,
140  hboost::is_base_of<TfRefBase, typename Ptr::DataType> > >::type>
141 {
142  struct _RefPtrHolder {
144  Get(Ptr const &refptr) {
145  TfPyLock pyLock;
146  _WrapIfNecessary();
147  return hboost::python::object(_RefPtrHolder(refptr));
148  }
149  static void _WrapIfNecessary() {
150  TfPyLock pyLock;
151  if (TfPyIsNone(TfPyGetClassObject<_RefPtrHolder>())) {
152  std::string name =
153  "__" + ArchGetDemangled(typeid(typename Ptr::DataType)) +
154  "__RefPtrHolder";
155  name = TfStringReplace(name, "<", "_");
156  name = TfStringReplace(name, ">", "_");
157  name = TfStringReplace(name, "::", "_");
158  hboost::python::class_<_RefPtrHolder>(name.c_str(),
159  hboost::python::no_init);
160  }
161  }
162  private:
163  explicit _RefPtrHolder(Ptr const &refptr) : _refptr(refptr) {}
164  Ptr _refptr;
165  };
166 
167  static void Add(Ptr ptr, const void *uniqueId, PyObject *self) {
168 
169  TfPyLock pyLock;
170 
171  // Make the python object keep the c++ object alive.
172  int ret = PyObject_SetAttrString(self, "__owner",
173  _RefPtrHolder::Get(ptr).ptr());
174  if (ret == -1) {
175  // CODE_COVERAGE_OFF
176  TF_WARN("Could not set __owner attribute on python object!");
177  PyErr_Clear();
178  return;
179  // CODE_COVERAGE_ON
180  }
181  TfRefBase *refBase =
182  static_cast<TfRefBase *>(get_pointer(ptr));
183  Tf_PyOwnershipPtrMap::Insert(refBase, uniqueId);
184  }
185 
186  static void Remove(Ptr ptr, PyObject *obj) {
187  TfPyLock pyLock;
188 
189  if (!ptr) {
190  // CODE_COVERAGE_OFF Can only happen if there's a bug.
191  TF_CODING_ERROR("Removing ownership from null/expired ptr!");
192  return;
193  // CODE_COVERAGE_ON
194  }
195 
196  if (PyObject_HasAttrString(obj, "__owner")) {
197  // We are guaranteed that ptr is not unique at this point,
198  // as __owner has a reference and ptr is itself a
199  // reference. This also guarantees us that the object owns
200  // a reference to its python object, so we don't need to
201  // explicitly acquire a reference here.
202  TF_AXIOM(!ptr->IsUnique());
203  // Remove this object from the cache of refbase to uniqueId
204  // that we use for python-owned things.
206  // Remove the __owner attribute.
207  if (PyObject_DelAttrString(obj, "__owner") == -1) {
208  // CODE_COVERAGE_OFF It's hard to make this occur.
209  TF_WARN("Undeletable __owner attribute on python object!");
210  PyErr_Clear();
211  // CODE_COVERAGE_ON
212  }
213  }
214  }
215 };
216 
217 #endif // doxygen -- see comment above.
218 
219 
220 template <typename Ptr>
222  static const bool value = false;
223 };
224 
225 template <typename T>
227  static const bool value = true;
228 };
229 
230 
231 template <class Ptr>
232 typename hboost::enable_if<Tf_PyIsRefPtr<Ptr> >::type
233 Tf_PySetPythonIdentity(Ptr const &, PyObject *)
234 {
235 }
236 
237 template <class Ptr>
238 typename hboost::disable_if<Tf_PyIsRefPtr<Ptr> >::type
239 Tf_PySetPythonIdentity(Ptr const &ptr, PyObject *obj)
240 {
241  if (ptr.GetUniqueIdentifier()) {
242  Tf_PyIdentityHelper::Set(ptr.GetUniqueIdentifier(), obj);
243  // Make sure we hear about it when this weak base dies so we can remove
244  // it from the map.
245  ptr.EnableExtraNotification();
246  }
247 }
248 
249 template <class Ptr>
250 PyObject *Tf_PyGetPythonIdentity(Ptr const &ptr)
251 {
252  PyObject *ret = Tf_PyIdentityHelper::Get(ptr.GetUniqueIdentifier());
253  return ret;
254 }
255 
256 template <class Ptr>
257 void Tf_PyRemovePythonOwnership(Ptr const &t, PyObject *obj)
258 {
260 }
261 
262 template <class Ptr>
263 void Tf_PyAddPythonOwnership(Ptr const &t, const void *uniqueId, PyObject *obj)
264 {
265  Tf_PyOwnershipHelper<Ptr>::Add(t, uniqueId, obj);
266 }
267 
269 
270 #endif // PXR_BASE_TF_PY_IDENTITY_H
#define TF_API
Definition: api.h:40
Y
Definition: ImathEuler.h:184
static void Add(U const &, const void *, PyObject *)
Definition: pyIdentity.h:131
static TF_API void const * Lookup(TfRefBase const *refBase)
#define TF_CODING_ERROR
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
X
Definition: ImathEuler.h:183
hboost::enable_if< Tf_PyIsRefPtr< Ptr > >::type Tf_PySetPythonIdentity(Ptr const &, PyObject *)
Definition: pyIdentity.h:233
GLuint object
Definition: glew.h:9028
GLuint const GLchar * name
Definition: glcorearb.h:786
GLdouble GLdouble t
Definition: glew.h:1403
static TF_API void Release(void const *id)
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:86
static TF_API void Erase(TfRefBase *refBase)
#define PXR_NS
Definition: pxr.h:71
TfHashMap< TfRefBase const *, void const *, TfHash > _CacheType
Definition: pyIdentity.h:108
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
#define TF_WARN
GLhandleARB obj
Definition: glew.h:6266
void Tf_PyRemovePythonOwnership(Ptr const &t, PyObject *obj)
Definition: pyIdentity.h:257
#define TF_AXIOM(cond)
static TF_API void Acquire(void const *id)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1394
static void Remove(U const &, PyObject *)
Definition: pyIdentity.h:133
void Tf_PyReleasePythonIdentity(Ptr const &ptr, PyObject *obj)
Definition: pyIdentity.h:96
void Tf_PyAddPythonOwnership(Ptr const &t, const void *uniqueId, PyObject *obj)
Definition: pyIdentity.h:263
auto ptr(T p) -> const void *
Definition: format.h:2448
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
static TF_API void Set(void const *id, PyObject *obj)
Definition: core.h:1131
static TF_API void Erase(void const *id)
PyObject * Tf_PyGetPythonIdentity(Ptr const &ptr)
Definition: pyIdentity.h:250
void Tf_PyOwnershipRefBaseUniqueChanged(TfRefBase const *refBase, bool isNowUnique)
type
Definition: core.h:1059
static TF_API PyObject * Get(void const *id)
TF_API bool TfPyIsNone(hboost::python::object const &obj)
Return true iff obj is None.
TF_API std::string TfStringReplace(const std::string &source, const std::string &from, const std::string &to)
static TF_API void Insert(TfRefBase *refBase, void const *uniqueId)