Core: new blenlib library for implicit-sharing #105994
|
@ -32,7 +32,7 @@ namespace blender::bke {
|
|||
* because that is not available in C code. If possible, the #AutoAnonymousAttributeID wrapper
|
||||
* should be used to avoid manual reference counting in C++ code.
|
||||
*/
|
||||
class AnonymousAttributeID : public bCopyOnWriteMixin {
|
||||
class AnonymousAttributeID : public ImplicitShareMixin {
|
||||
protected:
|
||||
std::string name_;
|
||||
|
||||
|
@ -54,7 +54,7 @@ class AnonymousAttributeID : public bCopyOnWriteMixin {
|
|||
};
|
||||
|
||||
/** Wrapper for #AnonymousAttributeID that avoids manual reference counting. */
|
||||
using AutoAnonymousAttributeID = COWUser<const AnonymousAttributeID>;
|
||||
using AutoAnonymousAttributeID = ImplicitSharePtr<const AnonymousAttributeID>;
|
||||
|
||||
/**
|
||||
* A set of anonymous attribute names that is passed around in geometry nodes.
|
||||
|
|
|
@ -43,7 +43,7 @@ class Instances;
|
|||
* copy-on-write behavior to avoid read-only copies. It also integrates with attribute API, which
|
||||
* generalizes storing and modifying generic information on a geometry.
|
||||
*/
|
||||
class GeometryComponent : public bCopyOnWriteMixin {
|
||||
class GeometryComponent : public blender::ImplicitShareMixin {
|
||||
private:
|
||||
GeometryComponentType type_;
|
||||
|
||||
|
@ -101,7 +101,7 @@ inline constexpr bool is_geometry_component_v = std::is_base_of_v<GeometryCompon
|
|||
*/
|
||||
struct GeometrySet {
|
||||
private:
|
||||
using GeometryComponentPtr = blender::COWUser<class GeometryComponent>;
|
||||
using GeometryComponentPtr = blender::ImplicitSharePtr<class GeometryComponent>;
|
||||
/* Indexed by #GeometryComponentType. */
|
||||
std::array<GeometryComponentPtr, GEO_COMPONENT_TYPE_ENUM_SIZE> components_;
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "BLI_utildefines.h"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/**
|
||||
* #bCopyOnWrite allows implementing copy-on-write behavior, i.e. it allows sharing read-only data
|
||||
* between multiple independend systems (e.g. meshes). The data is only copied when it is shared
|
||||
|
@ -30,18 +32,18 @@
|
|||
* #bCopyOnWrite is used in two ways:
|
||||
* - It can be allocated separately from the referenced data as is typically the case with raw
|
||||
* arrays (e.g. for mesh attributes).
|
||||
* - It can be embedded into another struct. For that it's best to use #bCopyOnWriteMixin.
|
||||
* - It can be embedded into another struct. For that it's best to use #ImplicitShareMixin.
|
||||
*/
|
||||
struct bCopyOnWrite : blender::NonCopyable, blender::NonMovable {
|
||||
struct ImplicitShareInfo : blender::NonCopyable, blender::NonMovable {
|
||||
private:
|
||||
mutable std::atomic<int> users_;
|
||||
|
||||
public:
|
||||
bCopyOnWrite(const int initial_users) : users_(initial_users)
|
||||
ImplicitShareInfo(const int initial_users) : users_(initial_users)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bCopyOnWrite()
|
||||
virtual ~ImplicitShareInfo()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
}
|
||||
|
@ -67,7 +69,7 @@ struct bCopyOnWrite : blender::NonCopyable, blender::NonMovable {
|
|||
BLI_assert(old_user_count >= 1);
|
||||
const bool was_last_user = old_user_count == 1;
|
||||
if (was_last_user) {
|
||||
const_cast<bCopyOnWrite *>(this)->delete_self_with_data();
|
||||
const_cast<ImplicitShareInfo *>(this)->delete_self_with_data();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,9 +81,9 @@ struct bCopyOnWrite : blender::NonCopyable, blender::NonMovable {
|
|||
/**
|
||||
* Makes it easy to embed copy-on-write behavior into a struct.
|
||||
*/
|
||||
JacquesLucke marked this conversation as resolved
Outdated
|
||||
struct bCopyOnWriteMixin : public bCopyOnWrite {
|
||||
struct ImplicitShareMixin : public ImplicitShareInfo {
|
||||
public:
|
||||
bCopyOnWriteMixin() : bCopyOnWrite(1)
|
||||
ImplicitShareMixin() : ImplicitShareInfo(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -94,3 +96,5 @@ struct bCopyOnWriteMixin : public bCopyOnWrite {
|
|||
|
||||
virtual void delete_self() = 0;
|
||||
};
|
||||
|
||||
} // namespace blender
|
||||
|
|
|
@ -10,33 +10,33 @@
|
|||
|
||||
namespace blender {
|
||||
|
||||
template<typename T> class COWUser {
|
||||
template<typename T> class ImplicitSharePtr {
|
||||
private:
|
||||
T *data_ = nullptr;
|
||||
|
||||
public:
|
||||
COWUser() = default;
|
||||
ImplicitSharePtr() = default;
|
||||
|
||||
COWUser(T *data) : data_(data)
|
||||
ImplicitSharePtr(T *data) : data_(data)
|
||||
{
|
||||
}
|
||||
|
||||
COWUser(const COWUser &other) : data_(other.data_)
|
||||
ImplicitSharePtr(const ImplicitSharePtr &other) : data_(other.data_)
|
||||
{
|
||||
this->add_user(data_);
|
||||
}
|
||||
|
||||
COWUser(COWUser &&other) : data_(other.data_)
|
||||
ImplicitSharePtr(ImplicitSharePtr &&other) : data_(other.data_)
|
||||
{
|
||||
other.data_ = nullptr;
|
||||
}
|
||||
|
||||
~COWUser()
|
||||
~ImplicitSharePtr()
|
||||
{
|
||||
this->remove_user_and_delete_if_last(data_);
|
||||
}
|
||||
|
||||
COWUser &operator=(const COWUser &other)
|
||||
ImplicitSharePtr &operator=(const ImplicitSharePtr &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
|
@ -48,7 +48,7 @@ template<typename T> class COWUser {
|
|||
return *this;
|
||||
}
|
||||
|
||||
COWUser &operator=(COWUser &&other)
|
||||
ImplicitSharePtr &operator=(ImplicitSharePtr &&other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
|
@ -122,7 +122,7 @@ template<typename T> class COWUser {
|
|||
return get_default_hash(data_);
|
||||
}
|
||||
|
||||
friend bool operator==(const COWUser &a, const COWUser &b)
|
||||
friend bool operator==(const ImplicitSharePtr &a, const ImplicitSharePtr &b)
|
||||
{
|
||||
return a.data_ == b.data_;
|
||||
}
|
||||
|
|
|
@ -226,8 +226,8 @@ struct GatherTasks {
|
|||
|
||||
/* Volumes only have very simple support currently. Only the first found volume is put into the
|
||||
* output. */
|
||||
COWUser<const VolumeComponent> first_volume;
|
||||
COWUser<const GeometryComponentEditData> first_edit_data;
|
||||
ImplicitSharePtr<const VolumeComponent> first_volume;
|
||||
ImplicitSharePtr<const GeometryComponentEditData> first_edit_data;
|
||||
};
|
||||
|
||||
/** Current offsets while during the gather operation. */
|
||||
|
|
Loading…
Reference in New Issue
This comment is a bit hard to follow, maybe replacing
the subclass
with something more specific would help (like saying the ptr class can be used with a class that derives from the mixin class).