| 319 | } |
| 320 | |
| 321 | py::capsule ExternalBuffer::dlpack(py::object stream) const |
| 322 | { |
| 323 | struct ManagerCtx |
| 324 | { |
| 325 | DLManagedTensor tensor; |
| 326 | std::shared_ptr<const ExternalBuffer> extBuffer; |
| 327 | }; |
| 328 | |
| 329 | auto ctx = std::make_unique<ManagerCtx>(); |
| 330 | |
| 331 | // Set up tensor deleter to delete the ManagerCtx |
| 332 | ctx->tensor.manager_ctx = ctx.get(); |
| 333 | ctx->tensor.deleter = [](DLManagedTensor *tensor) |
| 334 | { |
| 335 | auto *ctx = static_cast<ManagerCtx *>(tensor->manager_ctx); |
| 336 | delete ctx; |
| 337 | }; |
| 338 | |
| 339 | // Copy tensor data |
| 340 | ctx->tensor.dl_tensor = *m_dlTensor; |
| 341 | |
| 342 | // Manager context holds a reference to this External Buffer so that |
| 343 | // GC doesn't delete this buffer while the dlpack tensor still refers to it. |
| 344 | ctx->extBuffer = this->shared_from_this(); |
| 345 | |
| 346 | // Creates the python capsule with the DLManagedTensor instance we're returning. |
| 347 | py::capsule cap(&ctx->tensor, "dltensor", [](PyObject *ptr) |
| 348 | { |
| 349 | if(PyCapsule_IsValid(ptr, "dltensor")) |
| 350 | { |
| 351 | // If consumer didn't delete the tensor, |
| 352 | if(auto *dlTensor = static_cast<DLManagedTensor *>(PyCapsule_GetPointer(ptr, "dltensor"))) |
| 353 | { |
| 354 | // Delete the tensor. |
| 355 | if(dlTensor->deleter != nullptr) |
| 356 | { |
| 357 | dlTensor->deleter(dlTensor); |
| 358 | } |
| 359 | } |
| 360 | } |
| 361 | }); |
| 362 | |
| 363 | // Now that the capsule is created and the manager ctx was transfered to it, |
| 364 | // we can release the unique_ptr. |
| 365 | ctx.release(); |
| 366 | |
| 367 | return cap; |
| 368 | } |
| 369 | |
| 370 | py::tuple ExternalBuffer::dlpackDevice() const |
| 371 | { |
nothing calls this directly
no test coverage detected