Skip to content

Commit 129934a

Browse files
rwgkhenryiii
authored andcommitted
Small cleanup/refactoring in support of PR #5213 (#5251)
* Factor out detail/value_and_holder.h (from detail/type_caster_base.h) This is in support of PR #5213: * trampoline_self_life_support.h depends on value_and_holder.h * type_caster_base.h depends on trampoline_self_life_support.h * Fix a minor and inconsequential inconsistency in `copyable_holder_caster`: the correct `load_value()` return type is `void` (as defined in `type_caster_generic`) For easy future reference, this is the long-standing inconsistency: * https://github.com/pybind/pybind11/blob/dbf848aff7c37ef8798bc9459a86193e28b1032f/include/pybind11/detail/type_caster_base.h#L634 * https://github.com/pybind/pybind11/blob/dbf848aff7c37ef8798bc9459a86193e28b1032f/include/pybind11/cast.h#L797 Noticed in passing while working on PR #5213. * Add `DANGER ZONE` comment in detail/init.h, similar to a comment added on the smart_holder branch (all the way back in 2021).
1 parent f50830e commit 129934a

File tree

6 files changed

+86
-65
lines changed

6 files changed

+86
-65
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ set(PYBIND11_HEADERS
154154
include/pybind11/detail/internals.h
155155
include/pybind11/detail/type_caster_base.h
156156
include/pybind11/detail/typeid.h
157+
include/pybind11/detail/value_and_holder.h
157158
include/pybind11/attr.h
158159
include/pybind11/buffer_info.h
159160
include/pybind11/cast.h

include/pybind11/cast.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,11 +794,11 @@ struct copyable_holder_caster : public type_caster_base<type> {
794794
}
795795
}
796796

797-
bool load_value(value_and_holder &&v_h) {
797+
void load_value(value_and_holder &&v_h) {
798798
if (v_h.holder_constructed()) {
799799
value = v_h.value_ptr();
800800
holder = v_h.template holder<holder_type>();
801-
return true;
801+
return;
802802
}
803803
throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
804804
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)

include/pybind11/detail/init.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,13 @@ void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
128128
// the holder and destruction happens when we leave the C++ scope, and the holder
129129
// class gets to handle the destruction however it likes.
130130
v_h.value_ptr() = ptr;
131-
v_h.set_instance_registered(true); // To prevent init_instance from registering it
132-
v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder
131+
v_h.set_instance_registered(true); // Trick to prevent init_instance from registering it
132+
// DANGER ZONE BEGIN: exceptions will leave v_h in an invalid state.
133+
v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder
133134
Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder
134135
v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null
135136
v_h.set_instance_registered(false);
137+
// DANGER ZONE END.
136138

137139
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr));
138140
} else {

include/pybind11/detail/type_caster_base.h

Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "descr.h"
1515
#include "internals.h"
1616
#include "typeid.h"
17+
#include "value_and_holder.h"
1718

1819
#include <cstdint>
1920
#include <iterator>
@@ -259,67 +260,6 @@ PYBIND11_NOINLINE handle find_registered_python_instance(void *src,
259260
});
260261
}
261262

262-
struct value_and_holder {
263-
instance *inst = nullptr;
264-
size_t index = 0u;
265-
const detail::type_info *type = nullptr;
266-
void **vh = nullptr;
267-
268-
// Main constructor for a found value/holder:
269-
value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index)
270-
: inst{i}, index{index}, type{type},
271-
vh{inst->simple_layout ? inst->simple_value_holder
272-
: &inst->nonsimple.values_and_holders[vpos]} {}
273-
274-
// Default constructor (used to signal a value-and-holder not found by get_value_and_holder())
275-
value_and_holder() = default;
276-
277-
// Used for past-the-end iterator
278-
explicit value_and_holder(size_t index) : index{index} {}
279-
280-
template <typename V = void>
281-
V *&value_ptr() const {
282-
return reinterpret_cast<V *&>(vh[0]);
283-
}
284-
// True if this `value_and_holder` has a non-null value pointer
285-
explicit operator bool() const { return value_ptr() != nullptr; }
286-
287-
template <typename H>
288-
H &holder() const {
289-
return reinterpret_cast<H &>(vh[1]);
290-
}
291-
bool holder_constructed() const {
292-
return inst->simple_layout
293-
? inst->simple_holder_constructed
294-
: (inst->nonsimple.status[index] & instance::status_holder_constructed) != 0u;
295-
}
296-
// NOLINTNEXTLINE(readability-make-member-function-const)
297-
void set_holder_constructed(bool v = true) {
298-
if (inst->simple_layout) {
299-
inst->simple_holder_constructed = v;
300-
} else if (v) {
301-
inst->nonsimple.status[index] |= instance::status_holder_constructed;
302-
} else {
303-
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_holder_constructed;
304-
}
305-
}
306-
bool instance_registered() const {
307-
return inst->simple_layout
308-
? inst->simple_instance_registered
309-
: ((inst->nonsimple.status[index] & instance::status_instance_registered) != 0);
310-
}
311-
// NOLINTNEXTLINE(readability-make-member-function-const)
312-
void set_instance_registered(bool v = true) {
313-
if (inst->simple_layout) {
314-
inst->simple_instance_registered = v;
315-
} else if (v) {
316-
inst->nonsimple.status[index] |= instance::status_instance_registered;
317-
} else {
318-
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_instance_registered;
319-
}
320-
}
321-
};
322-
323263
// Container for accessing and iterating over an instance's values/holders
324264
struct values_and_holders {
325265
private:
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright (c) 2016-2024 The Pybind Development Team.
2+
// All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
#pragma once
6+
7+
#include "common.h"
8+
9+
#include <cstddef>
10+
#include <typeinfo>
11+
12+
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
13+
PYBIND11_NAMESPACE_BEGIN(detail)
14+
15+
struct value_and_holder {
16+
instance *inst = nullptr;
17+
size_t index = 0u;
18+
const detail::type_info *type = nullptr;
19+
void **vh = nullptr;
20+
21+
// Main constructor for a found value/holder:
22+
value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index)
23+
: inst{i}, index{index}, type{type},
24+
vh{inst->simple_layout ? inst->simple_value_holder
25+
: &inst->nonsimple.values_and_holders[vpos]} {}
26+
27+
// Default constructor (used to signal a value-and-holder not found by get_value_and_holder())
28+
value_and_holder() = default;
29+
30+
// Used for past-the-end iterator
31+
explicit value_and_holder(size_t index) : index{index} {}
32+
33+
template <typename V = void>
34+
V *&value_ptr() const {
35+
return reinterpret_cast<V *&>(vh[0]);
36+
}
37+
// True if this `value_and_holder` has a non-null value pointer
38+
explicit operator bool() const { return value_ptr() != nullptr; }
39+
40+
template <typename H>
41+
H &holder() const {
42+
return reinterpret_cast<H &>(vh[1]);
43+
}
44+
bool holder_constructed() const {
45+
return inst->simple_layout
46+
? inst->simple_holder_constructed
47+
: (inst->nonsimple.status[index] & instance::status_holder_constructed) != 0u;
48+
}
49+
// NOLINTNEXTLINE(readability-make-member-function-const)
50+
void set_holder_constructed(bool v = true) {
51+
if (inst->simple_layout) {
52+
inst->simple_holder_constructed = v;
53+
} else if (v) {
54+
inst->nonsimple.status[index] |= instance::status_holder_constructed;
55+
} else {
56+
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_holder_constructed;
57+
}
58+
}
59+
bool instance_registered() const {
60+
return inst->simple_layout
61+
? inst->simple_instance_registered
62+
: ((inst->nonsimple.status[index] & instance::status_instance_registered) != 0);
63+
}
64+
// NOLINTNEXTLINE(readability-make-member-function-const)
65+
void set_instance_registered(bool v = true) {
66+
if (inst->simple_layout) {
67+
inst->simple_instance_registered = v;
68+
} else if (v) {
69+
inst->nonsimple.status[index] |= instance::status_instance_registered;
70+
} else {
71+
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_instance_registered;
72+
}
73+
}
74+
};
75+
76+
PYBIND11_NAMESPACE_END(detail)
77+
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

tests/extra_python_package/test_files.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"include/pybind11/detail/internals.h",
5959
"include/pybind11/detail/type_caster_base.h",
6060
"include/pybind11/detail/typeid.h",
61+
"include/pybind11/detail/value_and_holder.h",
6162
}
6263

6364
eigen_headers = {

0 commit comments

Comments
 (0)