Skip to content

Commit e4a72a9

Browse files
Add dpctl::memory::usm_memory constructor from external allocation
usm_memory( void *usm_ptr, size_t nbytes, sycl::queue &q, std::shared_ptr<void> shptr) usm_ptr: Pointer to USM allocation nbytes: is the size of allocation in bytes q : sycl::queue associated with this allocation in Python. shptr: Smart pointer with custom deleter that deallocates the USM allocation.
1 parent d79dae1 commit e4a72a9

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

dpctl/apis/include/dpctl4pybind11.hpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,64 @@ class usm_memory : public py::object
748748
throw py::error_already_set();
749749
}
750750

751+
/*! @brief Create usm_memory object from shared pointer that manages
752+
* lifetime of the USM allocation.
753+
*/
754+
usm_memory(void *usm_ptr,
755+
size_t nbytes,
756+
const sycl::queue &q,
757+
std::shared_ptr<void> shptr)
758+
{
759+
auto const &api = ::dpctl::detail::dpctl_capi::get();
760+
DPCTLSyclUSMRef usm_ref = reinterpret_cast<DPCTLSyclUSMRef>(usm_ptr);
761+
sycl::queue *q_ptr = new sycl::queue(q);
762+
if (!q_ptr) {
763+
throw std::bad_alloc();
764+
}
765+
DPCTLSyclQueueRef QRef = reinterpret_cast<DPCTLSyclQueueRef>(q_ptr);
766+
767+
auto vacuous_destructor = []() {};
768+
py::object mock_owner = py::capsule(vacuous_destructor);
769+
770+
// create memory object owned by mock_owner, it is a new reference
771+
PyObject *_memory =
772+
api.Memory_Make_(usm_ref, nbytes, QRef, mock_owner.ptr());
773+
774+
bool is_ok =
775+
(PyObject_TypeCheck(
776+
_memory, ::dpctl::detail::dpctl_capi::get().Py_MemoryType_) !=
777+
0);
778+
779+
if (is_ok) {
780+
std::shared_ptr<void> *opaque_ptr =
781+
new std::shared_ptr<void>(shptr);
782+
if (!opaque_ptr) {
783+
Py_DECREF(_memory);
784+
delete q_ptr;
785+
throw std::bad_alloc();
786+
}
787+
Py_MemoryObject *memobj =
788+
reinterpret_cast<Py_MemoryObject *>(_memory);
789+
// replace mock_owner capsule as the owner
790+
memobj->refobj = Py_None;
791+
// set opaque ptr field, usm_memory now knowns that USM is managed
792+
// by smart pointer
793+
memobj->_opaque_ptr = reinterpret_cast<void *>(opaque_ptr);
794+
795+
// _memory will delete created copies of sycl::queue, and
796+
// std::shared_ptr and the deleter of the shared_ptr<void> is
797+
// supposed to free the USM allocation
798+
m_ptr = _memory;
799+
}
800+
else {
801+
delete q_ptr;
802+
Py_DECREF(_memory);
803+
804+
throw std::runtime_error(
805+
"Internal error: _Memory object created did not pass check");
806+
}
807+
}
808+
751809
sycl::queue get_queue() const
752810
{
753811
Py_MemoryObject *mem_obj = reinterpret_cast<Py_MemoryObject *>(m_ptr);

0 commit comments

Comments
 (0)