Core: new blenlib library for implicit-sharing #105994

Merged
Jacques Lucke merged 17 commits from JacquesLucke/blender:implicit-sharing into main 2023-03-28 13:58:02 +02:00
5 changed files with 26 additions and 22 deletions
Showing only changes of commit ab3fda1c58 - Show all commits

View File

@ -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.

View File

@ -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_;

View File

@ -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

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).

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).
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

View File

@ -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_;
}

View File

@ -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. */