Skip to content

Commit

Permalink
Split out (almost) pure refactoring from pybind/pybind11#5332 (#5334)
Browse files Browse the repository at this point in the history
PREPARATION for:

PR #5332 — Fix handling of const unique_ptr<T, D> & (do not disown).

Splitting out so that the functional changes under PR #5332 will be more obvious.

The only functional change under this PR is that

```
            assert(custom_deleter_ptr != nullptr);
```

is replaced with:

```
            if (custom_deleter_ptr == nullptr) {
                throw std::runtime_error(
                    std::string("smart_holder::extract_deleter() precondition failure (") + context
                    + ").");
            }
```
  • Loading branch information
Ralf W. Grosse-Kunstleve authored Aug 25, 2024
1 parent bf54ecd commit 0e49463
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 16 deletions.
16 changes: 16 additions & 0 deletions include/pybind11/detail/struct_smart_holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,22 @@ struct smart_holder {
vptr_del_ptr->armed_flag = armed_flag;
}

// Caller is responsible for precondition: ensure_compatible_rtti_uqp_del<T, D>() must succeed.
template <typename T, typename D>
std::unique_ptr<D> extract_deleter(const char *context) const {
auto *gd = std::get_deleter<guarded_delete>(vptr);
if (gd && gd->use_del_fun) {
const auto &custom_deleter_ptr = gd->del_fun.template target<custom_deleter<T, D>>();
if (custom_deleter_ptr == nullptr) {
throw std::runtime_error(
std::string("smart_holder::extract_deleter() precondition failure (") + context
+ ").");
}
return std::unique_ptr<D>(new D(std::move(custom_deleter_ptr->deleter)));
}
return nullptr;
}

static smart_holder from_raw_ptr_unowned(void *raw_ptr) {
smart_holder hld;
hld.vptr.reset(raw_ptr, [](void *) {});
Expand Down
17 changes: 1 addition & 16 deletions include/pybind11/detail/type_caster_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -794,22 +794,7 @@ struct load_helper : value_and_holder_helper {
"instance cannot safely be transferred to C++.");
}

// Temporary variable to store the extracted deleter in.
std::unique_ptr<D> extracted_deleter;

auto *gd = std::get_deleter<pybindit::memory::guarded_delete>(holder().vptr);
if (gd && gd->use_del_fun) { // Note the ensure_compatible_rtti_uqp_del<T, D>() call above.
// In struct_smart_holder, a custom deleter is always stored in a guarded delete.
// The guarded delete's std::function<void(void*)> actually points at the
// custom_deleter type, so we can verify it is of the custom deleter type and
// finally extract its deleter.
using custom_deleter_D = pybindit::memory::custom_deleter<T, D>;
const auto &custom_deleter_ptr = gd->del_fun.template target<custom_deleter_D>();
assert(custom_deleter_ptr != nullptr);
// Now that we have confirmed the type of the deleter matches the desired return
// value we can extract the function.
extracted_deleter = std::unique_ptr<D>(new D(std::move(custom_deleter_ptr->deleter)));
}
std::unique_ptr<D> extracted_deleter = holder().template extract_deleter<T, D>(context);

// Critical transfer-of-ownership section. This must stay together.
if (self_life_support != nullptr) {
Expand Down

0 comments on commit 0e49463

Please sign in to comment.