Skip to content

Commit

Permalink
WIP: Squashed commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
EricCousineau-TRI committed Oct 16, 2017
1 parent 86e2ad4 commit 9e7b022
Show file tree
Hide file tree
Showing 11 changed files with 1,109 additions and 63 deletions.
3 changes: 3 additions & 0 deletions include/pybind11/attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ struct type_record {
/// Function pointer to class_<..>::dealloc
void (*dealloc)(detail::value_and_holder &) = nullptr;

/// See `type_info::has_cpp_release`.
instance::type_release_info_t release_info;

/// List of base classes of the newly created type
list bases;

Expand Down
402 changes: 349 additions & 53 deletions include/pybind11/cast.h

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions include/pybind11/detail/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ enum class return_value_policy : uint8_t {
reference_internal
};

class object;

NAMESPACE_BEGIN(detail)

inline static constexpr int log2(size_t n, int k = 0) { return (n <= 1) ? k : log2(n >> 1, k + 1); }
Expand All @@ -373,6 +375,83 @@ constexpr size_t instance_simple_holder_in_ptrs() {
return size_in_ptrs(sizeof(std::shared_ptr<int>));
}

enum class HolderTypeId {
Unknown,
UniquePtr,
SharedPtr,
};
template <typename holder_type, typename SFINAE = void>
struct get_holder_type_id {
static constexpr HolderTypeId value = HolderTypeId::Unknown;
};
template <typename T>
struct get_holder_type_id<std::shared_ptr<T>, void> {
static constexpr HolderTypeId value = HolderTypeId::SharedPtr;
};
template <typename T, typename Deleter>
struct get_holder_type_id<std::unique_ptr<T, Deleter>, void> {
// TODO(eric.cousineau): Should this only specialize for `std::default_deleter`?
static constexpr HolderTypeId value = HolderTypeId::UniquePtr;
};

class holder_erased {
public:
holder_erased() = default;
holder_erased(const holder_erased&) = default;
holder_erased& operator=(const holder_erased&) = default;

template <typename holder_type>
holder_erased(const holder_type* holder)
: ptr_(const_cast<holder_type*>(holder)),
type_id_(get_holder_type_id<holder_type>::value),
is_const_(true) {}

template <typename holder_type>
holder_erased(holder_type* holder)
: holder_erased(static_cast<const holder_type*>(holder)) {
is_const_ = false;
}

holder_erased(const void* ptr, HolderTypeId type_id)
: ptr_(const_cast<void*>(ptr)),
type_id_(type_id),
is_const_(true) {}

holder_erased(void* ptr, HolderTypeId type_id)
: ptr_(ptr),
type_id_(type_id),
is_const_(false) {}

void* ptr() const { return ptr_; }
HolderTypeId type_id() const { return type_id_; }

template <typename holder_type>
holder_type& mutable_cast() const {
if (is_const_)
throw std::runtime_error("Trying to mutate const reference?");
return do_cast<holder_type>();
}

template <typename holder_type>
const holder_type& cast() const {
return do_cast<holder_type>();
}

operator bool() const { return ptr_; }
private:
template <typename holder_type>
holder_type& do_cast() const {
if (type_id_ != get_holder_type_id<holder_type>::value) {
throw std::runtime_error("Mismatch on holder type.");
}
return *reinterpret_cast<holder_type*>(ptr_);
}

void* ptr_{};
HolderTypeId type_id_{HolderTypeId::Unknown};
bool is_const_{true};
};

// Forward declarations
struct type_info;
struct value_and_holder;
Expand Down Expand Up @@ -423,6 +502,26 @@ struct instance {
/// If true, get_internals().patients has an entry for this object
bool has_patients : 1;

typedef void (*release_to_cpp_t)(instance* inst, holder_erased external_holder, object&& obj);
typedef object (*reclaim_from_cpp_t)(instance* inst, holder_erased external_holder);

struct type_release_info_t {
// Release an instance to C++ for pure C++ instances or Python-derived classes.
release_to_cpp_t release_to_cpp = nullptr;

// For classes wrapped in `wrapper<>`. See `move_only_holder_caster` for more info.
// Pure / direct C++ objects do not need any fancy releasing mechanisms. They are simply
// unwrapped and passed back.
bool can_derive_from_wrapper = false;

// The holder that is contained by this class.
HolderTypeId holder_type_id = HolderTypeId::Unknown;
};
/// If the instance is a Python-derived type that is owned in C++, then this method
/// will permit the instance to be reclaimed back by Python.
// TODO(eric.cousineau): This may not be necessary. See note in `type_caster_generic::cast`.
reclaim_from_cpp_t reclaim_from_cpp = nullptr;

/// Initializes all of the above type/values/holders data (but not the instance values themselves)
void allocate_layout();

Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ struct type_info {
bool default_holder : 1;
/* true if this is a type registered with py::module_local */
bool module_local : 1;

instance::type_release_info_t release_info;
};

/// Tracks the `internals` and `type_info` ABI version independent of the main library version
Expand Down
Loading

0 comments on commit 9e7b022

Please sign in to comment.