Skip to content

Commit

Permalink
Allow Collections to be owned by Collections
Browse files Browse the repository at this point in the history
  • Loading branch information
jedelbo committed Mar 28, 2023
1 parent 172a2b9 commit e239793
Show file tree
Hide file tree
Showing 17 changed files with 750 additions and 437 deletions.
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ let notSyncServerSources: [String] = [
"realm/cluster.cpp",
"realm/cluster_tree.cpp",
"realm/collection.cpp",
"realm/collection_parent.cpp",
"realm/column_binary.cpp",
"realm/db.cpp",
"realm/decimal128.cpp",
Expand Down
2 changes: 2 additions & 0 deletions src/realm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ set(REALM_SOURCES
chunked_binary.cpp
cluster.cpp
collection.cpp
collection_parent.cpp
cluster_tree.cpp
error_codes.cpp
column_binary.cpp
Expand Down Expand Up @@ -138,6 +139,7 @@ set(REALM_INSTALL_HEADERS
cluster.hpp
cluster_tree.hpp
collection.hpp
collection_parent.hpp
column_binary.hpp
column_fwd.hpp
column_integer.hpp
Expand Down
127 changes: 108 additions & 19 deletions src/realm/collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ class CollectionBase {
return ndx;
}

virtual void set_owner(const Obj& obj, CollectionParent::Index index) = 0;
virtual void set_owner(std::shared_ptr<CollectionParent> parent, CollectionParent::Index index) = 0;


StringData get_property_name() const
{
return get_table()->get_column_name(get_col_key());
Expand Down Expand Up @@ -339,9 +343,23 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {

const Obj& get_obj() const noexcept final
{
return m_obj;
return m_obj_mem;
}

ref_type get_collection_ref() const noexcept
{
try {
return m_parent->get_collection_ref(m_index);
}
catch (const KeyNotFound&) {
return ref_type(0);
}
}

void set_collection_ref(ref_type ref)
{
m_parent->set_collection_ref(m_index, ref);
}

/// Returns true if the accessor has changed since the last time
/// `has_changed()` was called.
Expand All @@ -364,12 +382,37 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
return false;
}

void set_owner(const Obj& obj, CollectionParent::Index index) override
{
m_obj_mem = obj;
m_parent = &m_obj_mem;
m_index = index;
if (obj) {
m_alloc = &obj.get_alloc();
}
}

void set_owner(std::shared_ptr<CollectionParent> parent, CollectionParent::Index index) override
{
m_obj_mem = parent->get_object();
m_col_parent = std::move(parent);
m_parent = m_col_parent.get();
m_index = index;
if (m_obj_mem) {
m_alloc = &m_obj_mem.get_alloc();
}
}

using Interface::get_owner_key;
using Interface::get_table;
using Interface::get_target_table;

protected:
Obj m_obj;
Obj m_obj_mem;
std::shared_ptr<CollectionParent> m_col_parent;
CollectionParent* m_parent = nullptr;
CollectionParent::Index m_index;
Allocator* m_alloc = nullptr;
ColKey m_col_key;
bool m_nullable = false;

Expand All @@ -379,18 +422,49 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
mutable uint_fast64_t m_last_content_version = 0;

CollectionBaseImpl() = default;
CollectionBaseImpl(const CollectionBaseImpl& other) = default;
CollectionBaseImpl(CollectionBaseImpl&& other) = default;
CollectionBaseImpl(const CollectionBaseImpl& other)
: m_obj_mem(other.m_obj_mem)
, m_col_parent(other.m_col_parent)
, m_parent(m_col_parent ? m_col_parent.get() : &m_obj_mem)
, m_index(other.m_index)
, m_alloc(other.m_alloc)
, m_col_key(other.m_col_key)
, m_nullable(other.m_nullable)
{
}

CollectionBaseImpl(const Obj& obj, ColKey col_key) noexcept
: m_obj(obj)
: m_obj_mem(obj)
, m_parent(&m_obj_mem)
, m_index(col_key)
, m_col_key(col_key)
, m_nullable(col_key.is_nullable())
{
if (obj) {
m_alloc = &m_obj_mem.get_alloc();
}
}

CollectionBaseImpl& operator=(const CollectionBaseImpl& other) = default;
CollectionBaseImpl& operator=(CollectionBaseImpl&& other) = default;
CollectionBaseImpl(ColKey col_key) noexcept
: m_col_key(col_key)
, m_nullable(col_key.is_nullable())
{
}

CollectionBaseImpl& operator=(const CollectionBaseImpl& other)
{
if (this != &other) {
m_obj_mem = other.m_obj_mem;
m_col_parent = other.m_col_parent;
m_parent = m_col_parent ? m_col_parent.get() : &m_obj_mem;
m_alloc = other.m_alloc;
m_index = other.m_index;
m_col_key = other.m_col_key;
m_nullable = other.m_nullable;
}

return *this;
}

bool operator==(const Derived& other) const noexcept
{
Expand Down Expand Up @@ -420,10 +494,10 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
/// `UpdateStatus::NoChange`, and the caller is allowed to not do anything.
virtual UpdateStatus update_if_needed() const
{
UpdateStatus status = m_obj.update_if_needed_with_status();
UpdateStatus status = m_parent ? m_parent->update_if_needed_with_status() : UpdateStatus::Detached;

if (status != UpdateStatus::Detached) {
auto content_version = m_obj.get_alloc().get_content_version();
auto content_version = m_alloc->get_content_version();
if (content_version != m_content_version) {
m_content_version = content_version;
status = UpdateStatus::Updated;
Expand All @@ -445,8 +519,8 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
/// method will never return `UpdateStatus::Detached`.
virtual UpdateStatus ensure_created()
{
bool changed = m_obj.update_if_needed(); // Throws if the object does not exist.
auto content_version = m_obj.get_alloc().get_content_version();
bool changed = m_parent->update_if_needed(); // Throws if the object does not exist.
auto content_version = m_alloc->get_content_version();

if (changed || content_version != m_content_version) {
m_content_version = content_version;
Expand All @@ -457,7 +531,7 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {

void bump_content_version()
{
m_content_version = m_obj.bump_content_version();
m_content_version = m_parent->bump_content_version();
}

/// Reset the accessor's tracking of the content version. Derived classes
Expand All @@ -474,18 +548,13 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
ref_type get_child_ref(size_t child_ndx) const noexcept final
{
static_cast<void>(child_ndx);
try {
return to_ref(m_obj._get<int64_t>(m_col_key.get_index()));
}
catch (const KeyNotFound&) {
return ref_type(0);
}
return get_collection_ref();
}

void update_child_ref(size_t child_ndx, ref_type new_ref) final
{
static_cast<void>(child_ndx);
m_obj.set_int(m_col_key, from_ref(new_ref));
set_collection_ref(new_ref);
}
};

Expand Down Expand Up @@ -765,6 +834,26 @@ struct CollectionIterator {
size_t m_ndx = size_t(-1);
};

template <class T>
class IteratorAdapter {
public:
IteratorAdapter(T* keys)
: m_list(keys)
{
}
CollectionIterator<T> begin() const
{
return CollectionIterator<T>(m_list, 0);
}
CollectionIterator<T> end() const
{
return CollectionIterator<T>(m_list, m_list->size());
}

private:
T* m_list;
};

} // namespace realm

#endif // REALM_COLLECTION_HPP
Loading

0 comments on commit e239793

Please sign in to comment.